180 likes | 308 Views
Pushin ’ Geo to the GPU (with a Hint of Shaders ). CS 4363/6353. Basic Problem. We need to be able to get our geometry to the GPU We also need 1) normal information and 2) texture coordinates To do this, we’ll ask the OpenGL driver to create a buffer object
E N D
Pushin’ Geo to the GPU(with a Hint of Shaders) CS 4363/6353
Basic Problem • We need to be able to get our geometry to the GPU • We also need 1) normal information and 2) texture coordinates • To do this, we’ll ask the OpenGL driver to create a buffer object • This is just a chunk of memory • Nothing to be afraid of! • Located on the GPU (probably) • Might be mapped to main memory (using the Graphics Address Remapping Table)
Before we work with buffers… • Vertex Array Objects (VAOs) • There are several “attributes” that you’ll be modifying • The vertex array object is a collection of those settings • Is a “pure state” object • Set it up once, then just call it before drawing! • Creating a vertex array object: // This will be the ID of the VAOGLuintvao; // Ask the driver for exactly 1 unique IDglGenVertexArrays(1, &vao); // Set the state. Everything after this will be part of// the VAOglBindVertexArray(vao); // Lots of buffer stuff
Working with Buffers • To create a buffer ID: // This is the ID of the bufferGLuint buffer; // Ask OpenGL to generate exactly 1 unique IDglGenBuffers(1, &buffer); • To set this buffer as the active one and specify which buffer we’re referring to: glBindBuffer(GL_ARRAY_BUFFER, &buffer); • Notes: • That buffer is now bound! • Any draws will come from that buffer
Loading the Buffer with Data • Assume data is a GLfloat* • To load the buffer with data (like a memcpy): glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); • Other drawing types GL_X_Y: • X • STREAM for infrequent use and changes • STATIC for frequent use and infrequent change • DYNAMIC for frequent use and frequent change • Y could be DRAW, READ or COPY Note: if you need to change the data, look into glBufferSubData( )
How do we link this to the VertShader? • We need to query the vertex shader program for its variables • The code below goes into the shader program and gets the “vPosition” ID GLuintvpos;vpos= glGetAttribLocation (programID, “vPosition”); • As always, we have to enable things (attributes, in this case): glEnableVertexAttribArray(vpos); // turn on vPosition • Finally, we set the location and tell it the format of the data in the buffer glVertexAttribPointer(vpos, 3, GL_FLOAT, GL_FALSE, 0, 0); void glVertexAttribPointer(GLuint index, GLint size, Glenum type, GLboolean normalized, GLsizei stride, constGLvoid* offset);
A Side-By-SIDE Comparison • Show the relationship between client code and shader code • Assume you loaded a sphere, plane, or monkey face… • numVertices – the number of vertices (duh!) • vVerts – the position information of each vertex • vNorms – the normal information of each vertex (later)
buffer glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); Note: buffer “lives” on the graphics card in a nice, two-bedroom loft…
Hey – I’m active now buffer glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
Now I know how big I am! buffer glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, numVertices*6*sizeof(GLfloat), NULL, GL_STATIC_DRAW); Why 6?
Now I’m putting vVerts at the beginning buffer vVerts glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, numVertices*6*sizeof(GLfloat), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*3*sizeof(GLfloat), vVerts); glBufferSubData (GL_ARRAY_BUFFER, numVertices*3*sizeof(GLfloat), numVertices*3*sizeof(GLfloat), vNorms); Put vVerts at 0… it’s pretty bigthough…
I’m putting vNormals next buffer vVerts vNorms glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, numVertices*6*sizeof(GLfloat), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*3*sizeof(GLfloat), vVerts); glBufferSubData (GL_ARRAY_BUFFER, numVertices*3*sizeof(GLfloat), numVertices*3*sizeof(GLfloat), vNorms); Put vNormals startingright after that! It’s pretty bigtoo…
What we Have so far… • We have a buffer with an ID • That buffer lives on the graphics card • That buffer is full of vertex position/normal data • The VAO remembers these settings! • How do we get that info to our shader? • Immediately after this code, we put the following…
GLuintloc = glGetAttribLocation(shaderProgramID, "vPosition"); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); } Find the variable “vPosition” inside the shader
Guys! I’m still active, remember? buffer GLuintloc = glGetAttribLocation(shaderProgramID, "vPosition");glEnableVertexAttribArray(loc);glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); } vVerts vNorms
Tell vNormal where to look in me… buffer vVerts vNorms GLuintloc2 = glGetAttribLocation(shaderProgramID, "vNormal");glEnableVertexAttribArray(loc2);glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertices*3*sizeof(GLfloat))); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); }
GLuintloc = glGetAttribLocation(shaderProgramID, "vPosition");glEnableVertexAttribArray(loc);glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0); GLuintloc2 = glGetAttribLocation(shaderProgramID, "vNormal");glEnableVertexAttribArray(loc2);glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertices*3*sizeof(GLfloat))); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); }