跳转到内容

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;

我试图获得 逐像素 后期效果,但这可以用于变形效果等。

2D 缩放作为着色器?

[编辑 | 编辑源代码]

Paul 告诉我

我刚刚意识到,位图有很多上采样算法
艺术作品,用 GPU 着色器和现代 OpenGL 实现其中一些
或所有算法,可能是一个有趣的练习。
http://research.microsoft.com/en-us/um/people/kopf/pixelart/supplementary/index.html
http://scale2x.sourceforge.net/

听起来是个好主意!

< OpenGL 编程

浏览并下载 完整代码

多个纹理和

着色器针对不同的三角形而改变

#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;
}
华夏公益教科书