OpenGL 编程/现代 OpenGL 教程草稿
外观
此外,我们可以设置背面剔除
- glEnable(GL_CULL_FACE); // 默认情况下禁用
- 行为由 glCullFace(GL_BACK) 和 glFrontFace(GL_CCW) 指定,默认情况下
在 GLSL_Programming/GLUT/切片 中介绍。
示例:显示一个旋转的立方体,其中一个面缺失 - 我们能看到立方体的内部吗?有哪些可能的解决方法?
- 使用 OpenAL 从麦克风捕获声音,将数据未经修改地上传到显卡,显示示波器信号。
- 对比度和亮度调整。
- 伽马校正。
- 使用小型卷积矩阵进行锐化/模糊。
- 使用多个纹理单元对 CCD/CMOS 图像执行暗场和亮场校正。
- 将多个曝光组合成一张 LDR 图像。
技术:我将从加载三个纹理开始,即 I、D 和 F,将它们绑定到单独的纹理单元,并在片段着色器中计算 (I - D) * F。对于伽马校正和小型卷积之类的事情,我将使用单个纹理,因此它可以应用于先前上传的内容或 FBO 的内容。
如果你的深度缓冲区精度较低,你想进行透明度处理,或者对于某些阴影技术,这很有用。
可以通过为每个顶点添加随机噪声来实现“水下”效果
GLint attribute_v_rand;
attribute_name = "v_rand";
attribute_v_rand = glGetAttribLocation(program, attribute_name);
if (attribute_v_rand == -1) {
fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
return 0;
}
mesh.rand.resize(mesh.vertices.size());
srand(glutGet(GLUT_ELAPSED_TIME) / 100);
for (int i = 0; i < mesh.rand.size(); i++)
mesh.rand[i] = 1.0f*rand()/RAND_MAX * 0.1;
glEnableVertexAttribArray(attribute_v_rand);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribPointer(
attribute_v_rand, // attribute
1, // number of elements per vertex
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
mesh.rand.data() // offset of first element
);
srand 每 1/10 秒修改一次,因此动画不会太疯狂。
attribute float v_rand;
gl_Position = mvp * v_coord;
gl_Position.x += v_rand;
gl_Position.y += v_rand;
我试图获得 逐像素 后期效果,但这可以用于变形效果等。
Paul 告诉我
- 我刚刚意识到,位图有很多上采样算法
- 艺术作品,用 GPU 着色器和现代 OpenGL 实现其中一些
- 或所有算法,可能是一个有趣的练习。
- http://research.microsoft.com/en-us/um/people/kopf/pixelart/supplementary/index.html
- http://scale2x.sourceforge.net/
听起来是个好主意!
浏览并下载 完整代码
多个纹理和
着色器针对不同的三角形而改变
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SOIL/SOIL.h>
#include <cstring>
const char* f_shader = ""
"varying vec2 f_texcoord;"
"uniform sampler2D mytexture;"
"void main(void) {"
" vec2 flipped_texcoord = vec2(f_texcoord.x, 1.0 - f_texcoord.y);"
" gl_FragColor = texture2D(mytexture, flipped_texcoord);"
"}";
const char* v_shader = ""
"attribute vec3 coord3d;"
"attribute vec2 texcoord;"
"varying vec2 f_texcoord;"
"uniform mat4 mvp;"
"uniform mat4 projMat;"
"void main(void) {"
" gl_Position = projMat * mvp * vec4(coord3d, 1.0);"
" f_texcoord = texcoord;"
"}";
typedef struct {
int width;
int height;
unsigned char* data;
}Image;
Image* images[2];
int screen_width=800, screen_height=600;
GLuint program;
GLuint texture_id[2];
GLint attribute_coord3d, attribute_texcoord;
GLint uniform_mvp, uniform_mytexture;
GLuint vbo_cube_vertices[2], vbo_cube_texcoords[2];
GLuint ibo_cube_elements[2];
GLuint create_shader(const char* source, GLenum type){
GLuint res = glCreateShader(type);
const GLchar* sources[] = {
#ifdef GL_ES_VERSION_2_0
"#version 100\n"
#else
"#version 120\n"
#endif
,
#ifdef GL_ES_VERSION_2_0
(type == GL_FRAGMENT_SHADER) ?
"#ifdef GL_FRAGMENT_PRECISION_HIGH \n"
"precision highp float; \n"
"#else \n"
"precision mediump float; \n"
"#endif \n"
: ""
#else
"#define lowp \n"
"#define mediump\n"
"#define highp \n"
#endif
,
source };
glShaderSource(res, 3, sources, NULL);
glCompileShader(res);
GLint compile_ok = GL_FALSE;
glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
if (compile_ok == GL_FALSE) {
glDeleteShader(res);
return 0;
}
return res;
}
Image* loadImage(const char* filename){
Image* image = (Image*) malloc(sizeof(Image));
int width;
image->data = SOIL_load_image(filename, &(image->width), &(image->height), NULL, 0);
return image;
}
void applyImage(Image* image, int index){
glBindTexture(GL_TEXTURE_2D, texture_id[index]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image->width, image->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->data);
}
int init_resources(){
GLfloat cube_vertices[] = {
// front
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
};
glGenBuffers(1, &vbo_cube_vertices[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
GLfloat cube_texcoords[2*4*6] = {
// front
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
};
//for (int i = 1; i < 6; i++)
// memcpy(&cube_texcoords[i*4*2], &cube_texcoords[0], 2*4*sizeof(GLfloat));
glGenBuffers(1, &vbo_cube_texcoords[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_texcoords), cube_texcoords, GL_STATIC_DRAW);
GLushort cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
};
glGenBuffers(1, &ibo_cube_elements[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
glGenTextures(1, &texture_id[0]);
images[0] = loadImage("image1.png");
applyImage(images[0], 0);
glGenTextures(1, &texture_id[1]);
images[1] = loadImage("image2.png");
applyImage(images[1], 1);
GLint link_ok = GL_FALSE;
GLuint vs, fs;
if ((vs = create_shader(v_shader, GL_VERTEX_SHADER)) == 0) return 0;
if ((fs = create_shader(f_shader, GL_FRAGMENT_SHADER)) == 0) return 0;
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
const char* attribute_name;
attribute_name = "coord3d";
attribute_coord3d = glGetAttribLocation(program, attribute_name);
attribute_name = "texcoord";
attribute_texcoord = glGetAttribLocation(program, attribute_name);
const char* uniform_name;
uniform_name = "mvp";
uniform_mvp = glGetUniformLocation(program, uniform_name);
uniform_name = "mytexture";
uniform_mytexture = glGetUniformLocation(program, uniform_name);
GLfloat cube_vertices2[] = {
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
};
glGenBuffers(1, &vbo_cube_vertices[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices2), cube_vertices2, GL_STATIC_DRAW);
GLfloat cube_texcoords2[2*4*6] = {
// front
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
};
glGenBuffers(1, &vbo_cube_texcoords[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_texcoords2), cube_texcoords2, GL_STATIC_DRAW);
GLushort cube_elements2[] = {
0, 1, 2,
2, 3, 0,
};
glGenBuffers(1, &ibo_cube_elements[1]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements2), cube_elements2, GL_STATIC_DRAW);
return 1;
}
void setTexture(int id){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id[id]);
glUniform1i(uniform_mytexture, 0);
}
void resetShader(){
unsigned int loc12 = glGetUniformLocation(program,"projMat");
glm::mat4 empty = glm::mat4(1.0);
glUniformMatrix4fv(loc12, 1, GL_FALSE, glm::value_ptr(empty));
}
void setShader(){
GLfloat angle = glutGet(GLUT_ELAPSED_TIME) / 1000.0 * 15;
glm::mat4 anim =
glm::rotate(glm::mat4(1.0f), angle*1.0f, glm::vec3(1, 0, 0)) *
glm::rotate(glm::mat4(1.0f), angle*1.0f, glm::vec3(0, 1, 0)) *
glm::rotate(glm::mat4(1.0f), angle*1.0f, glm::vec3(0, 0, 1)) ;
glm::mat4 schrink = glm::scale(glm::mat4(1.0f),glm::vec3(0.5f));
glm::mat4 final = anim;
glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(final));
}
void setScale() {
unsigned int loc1 = glGetUniformLocation(program,"projMat");
glm::mat4 schrink2 = glm::scale(glm::mat4(1.0f),glm::vec3(0.5f));
glUniformMatrix4fv(loc1, 1, GL_FALSE, glm::value_ptr(schrink2));
}
void setScale2() {
unsigned int loc1 = glGetUniformLocation(program,"projMat");
glm::mat4 schrink2 = glm::scale(glm::mat4(1.0f),glm::vec3(0.2f));
glUniformMatrix4fv(loc1, 1, GL_FALSE, glm::value_ptr(schrink2));
}
void onDisplay(){
setShader();
setScale();
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
setTexture(0);
// /*
glEnableVertexAttribArray(attribute_coord3d);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices[0]);
glVertexAttribPointer(attribute_coord3d, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(attribute_texcoord);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords[0]);
glVertexAttribPointer( attribute_texcoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements[0]);
int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
// */
resetShader();
setShader();
setScale2();
setTexture(1);
// /*
glEnableVertexAttribArray(attribute_coord3d);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices[1]);
glVertexAttribPointer(attribute_coord3d, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(attribute_texcoord);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords[1]);
glVertexAttribPointer( attribute_texcoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements[1]);
int size2; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size2);
glDrawElements(GL_TRIANGLES, size2/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
// */
glDisableVertexAttribArray(attribute_coord3d);
glDisableVertexAttribArray(attribute_texcoord);
glutSwapBuffers();
glutPostRedisplay();
}
void onReshape(int width, int height) {
screen_width = width;
screen_height = height;
glViewport(0, 0, screen_width, screen_height);
}
void free_resources(){
glDeleteProgram(program);
glDeleteBuffers(1, &vbo_cube_vertices[0]);
glDeleteBuffers(1, &vbo_cube_texcoords[0]);
glDeleteBuffers(1, &ibo_cube_elements[0]);
glDeleteTextures(1, &texture_id[0]);
glDeleteTextures(1, &texture_id[1]);
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_ALPHA|GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(screen_width, screen_height);
glutCreateWindow("My Textured Cube");
GLenum glew_status = glewInit();
if (init_resources() ) {
glutDisplayFunc(onDisplay);
glutReshapeFunc(onReshape);
// glutIdleFunc(onIdle);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutMainLoop();
}
free_resources();
return 0;
}