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;
}