2D | 3D |
---|---|
// In the main program … double xyz[6]; c.getOverallMCBoundingBox(xyz); ModelView::setMCRegionOfInterest(xyz); c.run(); |
// In the main program, we will do the same, but more: … double xyz[6]; c.getOverallMCBoundingBox(xyz); set3DViewingInformation(xyz); c.run(); where set3DViewingInformation(xyz) does:
|
void My2DModelView::defineModel() { glGenVertexArrays(numVAOsNeeded, VAOs); // for each VAO, i: glBindVertexArray(VAOs[i]); glGenBuffers(numVBOsNeeded, VBOs); // For each per-vertex attribute, j, in current VAO, use // glBindBuffer, glBufferData, et al. to send the data to the GPU. // For example, suppose PVA j are the vertex coordinates: glBindBuffer(VBOs[j]); // assume we have created an array of 2D coordinate // data in "coords". Assume there are "nCoords" 2D points. glBufferData(GL_ARRAY_BUFFER, nCoords*sizeof(vec2), coords, GL_STATIC_DRAW); glVertexAttribPointer(shaderIF->pvaLoc("mcPosition"), 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(shaderIF->pvaLoc("mcPosition")); // END: "For each per-vertex attribute, j, in current VAO" // END: "for each VAO, i" } |
void My3DModelView::defineModel() { glGenVertexArrays(numVAOsNeeded, VAOs); // for each VAO, i: glBindVertexArray(VAOs[i]); glGenBuffers(numVBOsNeeded, VBOs); // For each per-vertex attribute, j, in current VAO, use // glBindBuffer, glBufferData, et al. to send the data to the GPU. // For example, suppose PVA j are the vertex coordinates: glBindBuffer(VBOs[j]); // assume we have created an array of 3D coordinate // data in "coords". Assume there are "nCoords" 3D points. glBufferData(GL_ARRAY_BUFFER, nCoords*sizeof(vec3), coords, GL_STATIC_DRAW); glVertexAttribPointer(shaderIF->pvaLoc("mcPosition"), 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(shaderIF->pvaLoc("mcPosition")); // END: "For each per-vertex attribute, j, in current VAO" // END: "for each VAO, i" } |
If the object whose geometry is being defined is a curved surface, then there will most likely be another set of glBindBuffer-glBufferData-glVertexAttribPointer-glEnableVertexAttribArray calls (using shaderIF->pvaLoc("mcNormal")) to define 3D normal vectors for the vertices. If instead the normals are constant for large sections of the coordinate arrays, this is often handled using glVertexAttrib* calls between successive calls to routines like glDrawArrays in render. | |
void My2DModelView::render() { // save the current GLSL program in use int savedPgm; glGetIntegerv(GL_CURRENT_PROGRAM, &savedPgm); glUseProgram(shaderIF->getShaderPgmID()); // define the Window-Viewport map: MC to -1..+1 LDS: float scaleTrans[4]; computeScaleTrans(scaleTrans); glUniform4fv(shaderIF->ppuLoc("scaleTrans"), 1, scaleTrans); renderMy2DModelView(); glUseProgram(savedPgm); } |
void My3DModelView::render() { // save the current GLSL program in use int savedPgm; glGetIntegerv(GL_CURRENT_PROGRAM, &savedPgm); glUseProgram(shaderIF->getShaderPgmID()); // mc_ec: View orientation and dynamic rotation // ec_lds: 3D-2D projection, map to LDS, dynamic zoom: cryph::Matrix4x4 mc_ec, ec_lds; getMatrices(mc_ec, ec_lds); float m[16]; glUniformMatrix4fv(shaderIF->ppuLoc("mc_ec"), 1, false, mc_ec.extractColMajor(m)); glUniformMatrix4fv(shaderIF->ppuLoc("ec_lds"), 1, false, ec_lds.extractColMajor(m)); renderMy3DModelView(); glUseProgram(savedPgm); } |
#version 410 core // simple2d.vsh - A simplistic vertex shader that illustrates ONE WAY // to handle transformations from 2D MC to LDS. // Naming convention for variables holding coordinates: // mc - model coordinates // lds - logical device space uniform vec4 scaleTrans; // Per-vertex attributes in vec2 mcPosition; // incoming vertex position in model coordinates void main() { // transform mc to lds (equivalent to final line of // simple3d.vsh on the right) float ldsX = scaleTrans[0]*mcPosition[0] + scaleTrans[1]; float ldsY = scaleTrans[2]*mcPosition[1] + scaleTrans[3]; gl_Position = vec4(ldsX, ldsY, 0, 1); } |
#version 410 core // simple3d.vsh - A simple 3D vertex shader that illustrates ONE WAY // to handle viewing transformations and communication // with the fragment shader (responsible for lighting model) // Naming convention for variables holding coordinates: // mc - model coordinates // ec - eye coordinates // lds - logical device space // "p_" prefix on any of the preceding indicates the coordinates have been // embedded in projective space // (gl_Position would have label p_lds) // Transformation Matrices uniform mat4 mc_ec, // (dynamic rotations) * (ViewOrientation(E,C,up)) ec_lds; // (W-V map) * (projection matrix) // Per-vertex attributes in vec3 mcPosition; // incoming vertex position in model coordinates in vec3 mcNormal; // incoming normal vector in model coordinates // Pass on data that fragment shader will need for the lighing model: out PVA { vec3 ecPosition; svec3 ecUnitNormal; } pvaOut; void main () { // convert current vertex and its associated normal to eye coordinates vec4 p_ecPosition = mc_ec * vec4(mcPosition, 1.0); pvaOut.ecPosition = p_ecPosition.xyz/p_ecPosition.w; mat3 normalMatrix = transpose( inverse( mat3x3(mc_ec) ) ); pvaOut.ecUnitNormal = normalize(normalMatrix * mcNormal); // apply the projection matrix to compute the projective space representation // of the 3D logical device space coordinates of the input vertex: gl_Position = ec_lds * p_ecPosition; } |
Fragment Shader: We have seen a wide variety of techniques that can be used to generate a fragment color. | Fragment Shader: We will study and implement mathematical models that simulate light-surface interaction to obtain a fragment color. |