Jump to content

OpenGL Programming/Modern OpenGL Tutorial drafts

From Wikibooks, open books for an open world

Optimization

[edit | edit source]

In addition we can set up back-face culling:

  • glEnable(GL_CULL_FACE); // disabled by default
  • Behavior specified by glCullFace(GL_BACK) and glFrontFace(GL_CCW) by default

Covered in GLSL_Programming/GLUT/Cutaways.

Exemple: show a rotating cube with one of the facet missing - can we see inside the cube? What are the possible work-arounds?

Sound input

[edit | edit source]
  • Use OpenAL to capture sound from microphone, upload data unmodified to graphics card, display oscilloscope signal.

Image enhancement techniques

[edit | edit source]
  • Contrast and brightness adjustments.
  • Gamma correction.
  • Sharpening / blurring using small convolution matrices.
  • Using multiple texture units to perform darkfield and flatfield correction of CCD/CMOS images.
  • Combine multiple exposures into a single LDR image.

Technique: I will start with loading three textures, I, D and F, binding them to separate texture units, and calculating (I - D) * F in the fragment shader. For things like gamma correction and small convolutions I will use a single texture, so it can be applied either something that has been uploaded previously or the contents of a FBO.

Depth sorting

[edit | edit source]

Useful if your depth buffer has low precision, you want to do transparency, or for some shadow techniques

Vertex water effect

[edit | edit source]

One can achieve a "under water" effect by adding a random noise for each vertex:

GLintattribute_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);return0;}mesh.rand.resize(mesh.vertices.size());srand(glutGet(GLUT_ELAPSED_TIME)/100);for(inti=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,// attribute1,// number of elements per vertexGL_FLOAT,// the type of each elementGL_FALSE,// take our values as-is0,// no extra data between each positionmesh.rand.data()// offset of first element);

srand is modified every 1/10 second, so the animation is not too frenzy.

attributefloatv_rand;gl_Position=mvp*v_coord;gl_Position.x+=v_rand;gl_Position.y+=v_rand;

I was trying a get a per-pixel postfx but this could be used for morphing effects and such.

2D Scaling as shaders?

[edit | edit source]

Paul sends me:

I just realised that there are a ton of upscaling algorithms for bitmap
artwork and that it might be an interesting exercise to implement some
or all of them using GPU shaders and modern OpenGL.
http://research.microsoft.com/en-us/um/people/kopf/pixelart/supplementary/index.html
http://scale2x.sourceforge.net/

Sounds like a good idea!

< OpenGL Programming

Browse & download complete code

multiple textures and

shader changed for different triangles

#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>constchar*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);""}";constchar*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;""}";typedefstruct{intwidth;intheight;unsignedchar*data;}Image;Image*images[2];intscreen_width=800,screen_height=600;GLuintprogram;GLuinttexture_id[2];GLintattribute_coord3d,attribute_texcoord;GLintuniform_mvp,uniform_mytexture;GLuintvbo_cube_vertices[2],vbo_cube_texcoords[2];GLuintibo_cube_elements[2];GLuintcreate_shader(constchar*source,GLenumtype){GLuintres=glCreateShader(type);constGLchar*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);GLintcompile_ok=GL_FALSE;glGetShaderiv(res,GL_COMPILE_STATUS,&compile_ok);if(compile_ok==GL_FALSE){glDeleteShader(res);return0;}returnres;}Image*loadImage(constchar*filename){Image*image=(Image*)malloc(sizeof(Image));intwidth;image->data=SOIL_load_image(filename,&(image->width),&(image->height),NULL,0);returnimage;}voidapplyImage(Image*image,intindex){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);}intinit_resources(){GLfloatcube_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);GLfloatcube_texcoords[2*4*6]={// front0.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);GLushortcube_elements[]={// front0,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);GLintlink_ok=GL_FALSE;GLuintvs,fs;if((vs=create_shader(v_shader,GL_VERTEX_SHADER))==0)return0;if((fs=create_shader(f_shader,GL_FRAGMENT_SHADER))==0)return0;program=glCreateProgram();glAttachShader(program,vs);glAttachShader(program,fs);glLinkProgram(program);glGetProgramiv(program,GL_LINK_STATUS,&link_ok);constchar*attribute_name;attribute_name="coord3d";attribute_coord3d=glGetAttribLocation(program,attribute_name);attribute_name="texcoord";attribute_texcoord=glGetAttribLocation(program,attribute_name);constchar*uniform_name;uniform_name="mvp";uniform_mvp=glGetUniformLocation(program,uniform_name);uniform_name="mytexture";uniform_mytexture=glGetUniformLocation(program,uniform_name);GLfloatcube_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);GLfloatcube_texcoords2[2*4*6]={// front0.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);GLushortcube_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);return1;}voidsetTexture(intid){glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D,texture_id[id]);glUniform1i(uniform_mytexture,0);}voidresetShader(){unsignedintloc12=glGetUniformLocation(program,"projMat");glm::mat4empty=glm::mat4(1.0);glUniformMatrix4fv(loc12,1,GL_FALSE,glm::value_ptr(empty));}voidsetShader(){GLfloatangle=glutGet(GLUT_ELAPSED_TIME)/1000.0*15;glm::mat4anim=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::mat4schrink=glm::scale(glm::mat4(1.0f),glm::vec3(0.5f));glm::mat4final=anim;glUniformMatrix4fv(uniform_mvp,1,GL_FALSE,glm::value_ptr(final));}voidsetScale(){unsignedintloc1=glGetUniformLocation(program,"projMat");glm::mat4schrink2=glm::scale(glm::mat4(1.0f),glm::vec3(0.5f));glUniformMatrix4fv(loc1,1,GL_FALSE,glm::value_ptr(schrink2));}voidsetScale2(){unsignedintloc1=glGetUniformLocation(program,"projMat");glm::mat4schrink2=glm::scale(glm::mat4(1.0f),glm::vec3(0.2f));glUniformMatrix4fv(loc1,1,GL_FALSE,glm::value_ptr(schrink2));}voidonDisplay(){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]);intsize;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]);intsize2;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();}voidonReshape(intwidth,intheight){screen_width=width;screen_height=height;glViewport(0,0,screen_width,screen_height);}voidfree_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]);}intmain(intargc,char*argv[]){glutInit(&argc,argv);glutInitDisplayMode(GLUT_RGBA|GLUT_ALPHA|GLUT_DOUBLE|GLUT_DEPTH);glutInitWindowSize(screen_width,screen_height);glutCreateWindow("My Textured Cube");GLenumglew_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();return0;}
close