void MapOverlayBitmap::Draw(Canvas &canvas, const WindowProjection &projection) noexcept { if (!simple_bounds.Overlaps(projection.GetScreenBounds())) /* not visible, outside of screen area */ return; const RasterPoint vertices[] = { projection.GeoToScreen(bounds.top_left), projection.GeoToScreen(bounds.top_right), projection.GeoToScreen(bounds.bottom_left), projection.GeoToScreen(bounds.bottom_right), }; const ScopeVertexPointer vp(vertices); GLTexture &texture = *bitmap.GetNative(); texture.Bind(); const PixelSize allocated = texture.GetAllocatedSize(); const unsigned src_x = 0, src_y = 0; const unsigned src_width = texture.GetWidth(); const unsigned src_height = texture.GetHeight(); GLfloat x0 = (GLfloat)src_x / allocated.cx; GLfloat y0 = (GLfloat)src_y / allocated.cy; GLfloat x1 = (GLfloat)(src_x + src_width) / allocated.cx; GLfloat y1 = (GLfloat)(src_y + src_height) / allocated.cy; if (bitmap.IsFlipped()) { y0 = 1 - y0; y1 = 1 - y1; } const Point2D<GLfloat> coord[] = { {x0, y0}, {x1, y0}, {x0, y1}, {x1, y1}, }; const ScopeTextureConstantAlpha blend(alpha); #ifdef USE_GLSL OpenGL::texture_shader->Use(); glEnableVertexAttribArray(OpenGL::Attribute::TEXCOORD); glVertexAttribPointer(OpenGL::Attribute::TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, coord); #else const GLEnable<GL_TEXTURE_2D> scope; glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, coord); #endif glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); #ifdef USE_GLSL glDisableVertexAttribArray(OpenGL::Attribute::TEXCOORD); OpenGL::solid_shader->Use(); #else glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif }
void CoordinateSystemsComponent::Initialize() { std::vector<GLfloat> color{ 0.2f, 0.3f, 0.3f, 1.0f }; //Background color mVertices = { //FRONT FACE //Positions //Texture Coords. 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // Top Right = 0 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // Bottom Right = 1 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // Bottom Left = 2 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // Top Right = 0 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // Bottom Left = 2 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // Top Left = 3 //BACK FACE 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // Top Right = 0 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // Bottom Right = 1 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // Bottom Left = 2 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // Top Right = 0 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // Bottom Left = 2 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // Top Left = 3 //RIGHT FACE 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, //LEFT FACE -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, //TOP FACE 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, //BOTTOM FACE 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f }; mCubePositions = { glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(2.0f, 5.0f, -15.0f), glm::vec3(-1.5f, -2.2f, -2.5f), glm::vec3(-3.8f, -2.0f, -12.3f), glm::vec3(2.4f, -0.4f, -3.5f), glm::vec3(-1.7f, 3.0f, -7.5f), glm::vec3(1.3f, -2.0f, -2.5f), glm::vec3(1.5f, 2.0f, -2.5f), glm::vec3(1.5f, 0.2f, -1.5f), glm::vec3(-1.3f, 1.0f, -1.5f) }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, mVertices.size() * sizeof(GLfloat), &mVertices[0], GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glBindVertexArray(0); mShader = Shader("shaders/vertexshader.vert", "shaders/fragmentshader.frag"); //---------- TEXTURE ----------// mTextureContainer.SetProgram(mShader.Program()); mTextureContainer.BindTexture(GL_TEXTURE0); mTextureContainer.SetTextureParameter(GL_TEXTURE_WRAP_S, GL_REPEAT); mTextureContainer.SetTextureParameter(GL_TEXTURE_WRAP_T, GL_REPEAT); mTextureContainer.SetTextureParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); mTextureContainer.SetTextureParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR); mTextureContainer.LoadTexture("res\\container.jpg"); mTextureContainer.GenerateTexture(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE); mTextureContainer.GenerateMipmaps(); mTextureContainer.FreeImageData(); mTextureContainer.UnbindTexture(); mTextureAwesomeFace.SetProgram(mShader.Program()); mTextureAwesomeFace.BindTexture(GL_TEXTURE1); mTextureAwesomeFace.SetTextureParameter(GL_TEXTURE_WRAP_S, GL_REPEAT); mTextureAwesomeFace.SetTextureParameter(GL_TEXTURE_WRAP_T, GL_REPEAT); mTextureAwesomeFace.SetTextureParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); mTextureAwesomeFace.SetTextureParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR); mTextureAwesomeFace.LoadTexture("res\\awesomeface.png"); mTextureAwesomeFace.GenerateTexture(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE); mTextureAwesomeFace.GenerateMipmaps(); mTextureAwesomeFace.FreeImageData(); mTextureAwesomeFace.UnbindTexture(); }
int main() { int width = 640; int height = 480; sf::Window window(sf::VideoMode(width, height), "sfml", sf::Style::Default, sf::ContextSettings(0,0,0,3,3)); // using glew since sfml doesn create a core context if(glewInit()) { std::cerr << "failed to init GLEW" << std::endl; return 1; } // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); if(!check_program_link_status(shader_program)) { return 1; } // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z R G B 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 }; // 6 vertices with 6 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); bool closed = false; while(!closed) { sf::Event event; while(window.pollEvent(event)) { if(event.type == sf::Event::Closed) { closed = true; } } // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_TRIANGLES, 0, 6); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << error << std::endl; break; } // finally swap buffers window.display(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); return 0; }
JNIEXPORT void JNICALL Java_com_qualcomm_QCARSamples_VideoPlayback_VideoPlaybackRenderer_renderFrame(JNIEnv *, jobject) { //LOG("Java_com_qualcomm_QCARSamples_VideoPlayback_GLRenderer_renderFrame"); // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Get the state from QCAR and mark the beginning of a rendering section QCAR::State state = QCAR::Renderer::getInstance().begin(); // Explicitly render the Video Background QCAR::Renderer::getInstance().drawVideoBackground(); glEnable(GL_DEPTH_TEST); // We must detect if background reflection is active and adjust the culling direction. // If the reflection is active, this means the post matrix has been reflected as well, // therefore standard counter clockwise face culling will result in "inside out" models. glEnable(GL_CULL_FACE); glCullFace(GL_BACK); if(QCAR::Renderer::getInstance().getVideoBackgroundConfig().mReflection == QCAR::VIDEO_BACKGROUND_REFLECTION_ON) glFrontFace(GL_CW); //Front camera else glFrontFace(GL_CCW); //Back camera for (int i=0; i<NUM_TARGETS; i++) { isTracking[i] = false; targetPositiveDimensions[i].data[0] = 0.0; targetPositiveDimensions[i].data[1] = 0.0; } // Did we find any trackables this frame? for(int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++) { // Get the trackable: const QCAR::TrackableResult* trackableResult = state.getTrackableResult(tIdx); const QCAR::ImageTarget& imageTarget = (const QCAR::ImageTarget&) trackableResult->getTrackable(); int currentTarget; // We store the modelview matrix to be used later by the tap calculation if (strcmp(imageTarget.getName(), "stones") == 0) currentTarget=STONES; else currentTarget=CHIPS; modelViewMatrix[currentTarget] = QCAR::Tool::convertPose2GLMatrix(trackableResult->getPose()); isTracking[currentTarget] = true; targetPositiveDimensions[currentTarget] = imageTarget.getSize(); // The pose delivers the center of the target, thus the dimensions // go from -width/2 to width/2, same for height targetPositiveDimensions[currentTarget].data[0] /= 2.0f; targetPositiveDimensions[currentTarget].data[1] /= 2.0f; // If the movie is ready to start playing or it has reached the end // of playback we render the keyframe if ((currentStatus[currentTarget] == READY) || (currentStatus[currentTarget] == REACHED_END) || (currentStatus[currentTarget] == NOT_READY) || (currentStatus[currentTarget] == ERROR)) { QCAR::Matrix44F modelViewMatrixKeyframe = QCAR::Tool::convertPose2GLMatrix(trackableResult->getPose()); QCAR::Matrix44F modelViewProjectionKeyframe; SampleUtils::translatePoseMatrix(0.0f, 0.0f, targetPositiveDimensions[currentTarget].data[0], &modelViewMatrixKeyframe.data[0]); // Here we use the aspect ratio of the keyframe since it // is likely that it is not a perfect square float ratio=1.0; if (textures[currentTarget]->mSuccess) ratio = keyframeQuadAspectRatio[currentTarget]; else ratio = targetPositiveDimensions[currentTarget].data[1] / targetPositiveDimensions[currentTarget].data[0]; SampleUtils::scalePoseMatrix(targetPositiveDimensions[currentTarget].data[0], targetPositiveDimensions[currentTarget].data[0]*ratio, targetPositiveDimensions[currentTarget].data[0], &modelViewMatrixKeyframe.data[0]); SampleUtils::multiplyMatrix(&projectionMatrix.data[0], &modelViewMatrixKeyframe.data[0] , &modelViewProjectionKeyframe.data[0]); glUseProgram(keyframeShaderID); // Prepare for rendering the keyframe glVertexAttribPointer(keyframeVertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadVertices[0]); glVertexAttribPointer(keyframeNormalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadNormals[0]); glVertexAttribPointer(keyframeTexCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadTexCoords[0]); glEnableVertexAttribArray(keyframeVertexHandle); glEnableVertexAttribArray(keyframeNormalHandle); glEnableVertexAttribArray(keyframeTexCoordHandle); glActiveTexture(GL_TEXTURE0); // The first loaded texture from the assets folder is the keyframe glBindTexture(GL_TEXTURE_2D, textures[currentTarget]->mTextureID); glUniformMatrix4fv(keyframeMVPMatrixHandle, 1, GL_FALSE, (GLfloat*)&modelViewProjectionKeyframe.data[0] ); glUniform1i(keyframeTexSampler2DHandle, 0 /*GL_TEXTURE0*/); // Render glDrawElements(GL_TRIANGLES, NUM_QUAD_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &quadIndices[0]); glDisableVertexAttribArray(keyframeVertexHandle); glDisableVertexAttribArray(keyframeNormalHandle); glDisableVertexAttribArray(keyframeTexCoordHandle); glUseProgram(0); } else // In any other case, such as playing or paused, we render the actual contents { QCAR::Matrix44F modelViewMatrixVideo = QCAR::Tool::convertPose2GLMatrix(trackableResult->getPose()); QCAR::Matrix44F modelViewProjectionVideo; SampleUtils::translatePoseMatrix(0.0f, 0.0f, targetPositiveDimensions[currentTarget].data[0], &modelViewMatrixVideo.data[0]); // Here we use the aspect ratio of the video frame SampleUtils::scalePoseMatrix(targetPositiveDimensions[currentTarget].data[0], targetPositiveDimensions[currentTarget].data[0]*videoQuadAspectRatio[currentTarget], targetPositiveDimensions[currentTarget].data[0], &modelViewMatrixVideo.data[0]); SampleUtils::multiplyMatrix(&projectionMatrix.data[0], &modelViewMatrixVideo.data[0] , &modelViewProjectionVideo.data[0]); glUseProgram(videoPlaybackShaderID); // Prepare for rendering the keyframe glVertexAttribPointer(videoPlaybackVertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadVertices[0]); glVertexAttribPointer(videoPlaybackNormalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadNormals[0]); if (strcmp(imageTarget.getName(), "stones") == 0) glVertexAttribPointer(videoPlaybackTexCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &videoQuadTextureCoordsTransformedStones[0]); else glVertexAttribPointer(videoPlaybackTexCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &videoQuadTextureCoordsTransformedChips[0]); glEnableVertexAttribArray(videoPlaybackVertexHandle); glEnableVertexAttribArray(videoPlaybackNormalHandle); glEnableVertexAttribArray(videoPlaybackTexCoordHandle); glActiveTexture(GL_TEXTURE0); // IMPORTANT: // Notice here that the texture that we are binding is not the // typical GL_TEXTURE_2D but instead the GL_TEXTURE_EXTERNAL_OES glBindTexture(GL_TEXTURE_EXTERNAL_OES, videoPlaybackTextureID[currentTarget]); glUniformMatrix4fv(videoPlaybackMVPMatrixHandle, 1, GL_FALSE, (GLfloat*)&modelViewProjectionVideo.data[0]); glUniform1i(videoPlaybackTexSamplerOESHandle, 0 /*GL_TEXTURE0*/); // Render glDrawElements(GL_TRIANGLES, NUM_QUAD_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &quadIndices[0]); glDisableVertexAttribArray(videoPlaybackVertexHandle); glDisableVertexAttribArray(videoPlaybackNormalHandle); glDisableVertexAttribArray(videoPlaybackTexCoordHandle); glUseProgram(0); } // The following section renders the icons. The actual textures used // are loaded from the assets folder /* if ((currentStatus[currentTarget] == READY) || (currentStatus[currentTarget] == REACHED_END) || (currentStatus[currentTarget] == PAUSED) || (currentStatus[currentTarget] == NOT_READY) || (currentStatus[currentTarget] == ERROR)) { // If the movie is ready to be played, pause, has reached end or is not // ready then we display one of the icons QCAR::Matrix44F modelViewMatrixButton = QCAR::Tool::convertPose2GLMatrix(trackableResult->getPose()); QCAR::Matrix44F modelViewProjectionButton; glDepthFunc(GL_LEQUAL); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // The inacuracy of the rendering process in some devices means that // even if we use the "Less or Equal" version of the depth function // it is likely that we will get ugly artifacts // That is the translation in the Z direction is slightly different // Another posibility would be to use a depth func "ALWAYS" but // that is typically not a good idea SampleUtils::translatePoseMatrix(0.0f, 0.0f, targetPositiveDimensions[currentTarget].data[1]/1.98f, &modelViewMatrixButton.data[0]); SampleUtils::scalePoseMatrix((targetPositiveDimensions[currentTarget].data[1]/2.0f), (targetPositiveDimensions[currentTarget].data[1]/2.0f), (targetPositiveDimensions[currentTarget].data[1]/2.0f), &modelViewMatrixButton.data[0]); SampleUtils::multiplyMatrix(&projectionMatrix.data[0], &modelViewMatrixButton.data[0] , &modelViewProjectionButton.data[0]); glUseProgram(keyframeShaderID); glVertexAttribPointer(keyframeVertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadVertices[0]); glVertexAttribPointer(keyframeNormalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadNormals[0]); glVertexAttribPointer(keyframeTexCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &quadTexCoords[0]); glEnableVertexAttribArray(keyframeVertexHandle); glEnableVertexAttribArray(keyframeNormalHandle); glEnableVertexAttribArray(keyframeTexCoordHandle); glActiveTexture(GL_TEXTURE0); // Depending on the status in which we are we choose the appropriate // texture to display. Notice that unlike the video these are regular // GL_TEXTURE_2D textures switch (currentStatus[currentTarget]) { case READY: glBindTexture(GL_TEXTURE_2D, textures[2]->mTextureID); break; case REACHED_END: glBindTexture(GL_TEXTURE_2D, textures[2]->mTextureID); break; case PAUSED: glBindTexture(GL_TEXTURE_2D, textures[2]->mTextureID); break; case NOT_READY: glBindTexture(GL_TEXTURE_2D, textures[3]->mTextureID); break; case ERROR: glBindTexture(GL_TEXTURE_2D, textures[4]->mTextureID); break; default: glBindTexture(GL_TEXTURE_2D, textures[3]->mTextureID); break; } glUniformMatrix4fv(keyframeMVPMatrixHandle, 1, GL_FALSE, (GLfloat*)&modelViewProjectionButton.data[0] ); glUniform1i(keyframeTexSampler2DHandle, 0 /*GL_TEXTURE0/); // Render glDrawElements(GL_TRIANGLES, NUM_QUAD_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &quadIndices[0]); glDisableVertexAttribArray(keyframeVertexHandle); glDisableVertexAttribArray(keyframeNormalHandle); glDisableVertexAttribArray(keyframeTexCoordHandle); glUseProgram(0); // Finally we return the depth func to its original state glDepthFunc(GL_LESS); glDisable(GL_BLEND); } */ SampleUtils::checkGlError("VideoPlayback renderFrame"); } glDisable(GL_DEPTH_TEST); QCAR::Renderer::getInstance().end(); }
void R_DrawParticles (void) { particle_t *p, *kill; float grav; int i; float time2, time3; float time1; float dvel; float frametime; #ifdef GLQUAKE vec3_t up, right; float scale; GL_Use (gl_coloredpolygon1textureprogram); glUniformMatrix4fv(gl_coloredpolygon1textureprogram_transform, 1, 0, gl_polygon_matrix); GL_Bind(particletexture); glEnable (GL_BLEND); VectorScale (vup, 1.5, up); VectorScale (vright, 1.5, right); #else D_StartParticles (); VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); #endif frametime = cl.time - cl.oldtime; time3 = frametime * 15; time2 = frametime * 10; // 15; time1 = frametime * 5; grav = frametime * sv_gravity.value * 0.05; dvel = 4*frametime; for ( ;; ) { kill = active_particles; if (kill && kill->die < cl.time) { active_particles = kill->next; kill->next = free_particles; free_particles = kill; continue; } break; } #ifdef GLQUAKE int mark = Hunk_LowMark(); int vertexcount = 0; for (p=active_particles ; p ; p=p->next) { vertexcount += 3; } if (vertexcount == 0) return; GLfloat* vertices = Hunk_AllocName (vertexcount * 9 * sizeof(GLfloat), "vertex_buffer"); int vertexpos = 0; #endif for (p=active_particles ; p ; p=p->next) { for ( ;; ) { kill = p->next; if (kill && kill->die < cl.time) { p->next = kill->next; kill->next = free_particles; free_particles = kill; continue; } break; } #ifdef GLQUAKE // hack a scale up to keep particles from disapearing scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + (p->org[2] - r_origin[2])*vpn[2]; if (scale < 20) scale = 1; else scale = 1 + scale * 0.004; unsigned c = d_8to24table[(int)p->color]; GLfloat r = (GLfloat)(c & 0xFF) / 255.0; GLfloat g = (GLfloat)((c >> 8) & 0xFF) / 255.0; GLfloat b = (GLfloat)((c >> 16) & 0xFF) / 255.0; GLfloat a = (GLfloat)((c >> 24) & 0xFF) / 255.0; vertices[vertexpos++] = p->org[0]; vertices[vertexpos++] = p->org[1]; vertices[vertexpos++] = p->org[2]; vertices[vertexpos++] = r; vertices[vertexpos++] = g; vertices[vertexpos++] = b; vertices[vertexpos++] = a; vertices[vertexpos++] = 0.0; vertices[vertexpos++] = 0.0; vertices[vertexpos++] = p->org[0] + up[0] * scale; vertices[vertexpos++] = p->org[1] + up[1] * scale; vertices[vertexpos++] = p->org[2] + up[2] * scale; vertices[vertexpos++] = r; vertices[vertexpos++] = g; vertices[vertexpos++] = b; vertices[vertexpos++] = a; vertices[vertexpos++] = 1.0; vertices[vertexpos++] = 0.0; vertices[vertexpos++] = p->org[0] + right[0] * scale; vertices[vertexpos++] = p->org[1] + right[1] * scale; vertices[vertexpos++] = p->org[2] + right[2] * scale; vertices[vertexpos++] = r; vertices[vertexpos++] = g; vertices[vertexpos++] = b; vertices[vertexpos++] = a; vertices[vertexpos++] = 0.0; vertices[vertexpos++] = 1.0; #else D_DrawParticle (p); #endif p->org[0] += p->vel[0]*frametime; p->org[1] += p->vel[1]*frametime; p->org[2] += p->vel[2]*frametime; switch (p->type) { case pt_static: break; case pt_fire: p->ramp += time1; if (p->ramp >= 6) p->die = -1; else p->color = ramp3[(int)p->ramp]; p->vel[2] += grav; break; case pt_explode: p->ramp += time2; if (p->ramp >=8) p->die = -1; else p->color = ramp1[(int)p->ramp]; for (i=0 ; i<3 ; i++) p->vel[i] += p->vel[i]*dvel; p->vel[2] -= grav; break; case pt_explode2: p->ramp += time3; if (p->ramp >=8) p->die = -1; else p->color = ramp2[(int)p->ramp]; for (i=0 ; i<3 ; i++) p->vel[i] -= p->vel[i]*frametime; p->vel[2] -= grav; break; case pt_blob: for (i=0 ; i<3 ; i++) p->vel[i] += p->vel[i]*dvel; p->vel[2] -= grav; break; case pt_blob2: for (i=0 ; i<2 ; i++) p->vel[i] -= p->vel[i]*dvel; p->vel[2] -= grav; break; case pt_grav: #ifdef QUAKE2 p->vel[2] -= grav * 20; break; #endif case pt_slowgrav: p->vel[2] -= grav; break; } } #ifdef GLQUAKE GLuint vertexbuffer; glGenBuffers(1, &vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glBufferData(GL_ARRAY_BUFFER, vertexcount * 9 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(gl_coloredpolygon1textureprogram_position); glVertexAttribPointer(gl_coloredpolygon1textureprogram_position, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (const GLvoid *)0); glEnableVertexAttribArray(gl_coloredpolygon1textureprogram_color); glVertexAttribPointer(gl_coloredpolygon1textureprogram_color, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (const GLvoid *)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(gl_coloredpolygon1textureprogram_texcoords); glVertexAttribPointer(gl_coloredpolygon1textureprogram_texcoords, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (const GLvoid *)(7 * sizeof(GLfloat))); glDrawArrays(GL_TRIANGLES, 0, vertexcount); glDisableVertexAttribArray(gl_coloredpolygon1textureprogram_texcoords); glDisableVertexAttribArray(gl_coloredpolygon1textureprogram_color); glDisableVertexAttribArray(gl_coloredpolygon1textureprogram_position); glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &vertexbuffer); Hunk_FreeToLowMark (mark); glDisable (GL_BLEND); #else D_EndParticles (); #endif }
int main(int argc, char *argv[]) { ShaderProgram program = setup(); Matrix paddle_left_matrix; Matrix paddle_right_matrix; Matrix ball_matrix; Matrix view_matrix; Matrix projection_matrix; GLuint chartreuse_texture_ID = load_texture_rgb("chartreuse.png"); projection_matrix.setOrthoProjection(-3.55f, 3.55f, -2.0f, 2.0f, -1.0f, 1.0f); SDL_Event event; bool done = false; bool game_started = false; Paddle paddle_left(-3.5f, -3.4f, 0.5f, -0.5f); Paddle paddle_right(3.4f, 3.5f, 0.5f, -0.5f); Ball ball(0.0f, 0.0f, 0.05f, 0.0025f, (float)rand(), (float)rand()); while (!done) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Controls for the game while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT || event.type == SDL_WINDOWEVENT_CLOSE) done = true; if (event.type == SDL_KEYDOWN) { // left paddle if (event.key.keysym.scancode == SDL_SCANCODE_W) { if (paddle_left.top < 2.0f){ paddle_left.top += 0.3f; paddle_left.bottom += 0.3f; paddle_left_matrix.Translate(0.0f, 0.3f, 0.0f); } } if (event.key.keysym.scancode == SDL_SCANCODE_S) { if (paddle_left.bottom > -2.0f){ paddle_left.top -= 0.3f; paddle_left.bottom -= 0.3f; paddle_left_matrix.Translate(0.0f, -0.3f, 0.0f); } } // right paddle if (event.key.keysym.scancode == SDL_SCANCODE_UP) { if (paddle_right.top < 2.0f){ paddle_right.top += 0.3f; paddle_right.bottom += 0.3f; paddle_right_matrix.Translate(0.0f, 0.3f, 0.0f); } } if (event.key.keysym.scancode == SDL_SCANCODE_DOWN) { if (paddle_right.bottom > -2.0f){ paddle_right.top -= 0.3f; paddle_right.bottom -= 0.3f; paddle_right_matrix.Translate(0.0f, -0.3f, 0.0f); } } if (event.key.keysym.scancode == SDL_SCANCODE_SPACE || event.key.keysym.scancode == SDL_SCANCODE_RETURN) { if (!game_started) game_started = true; } } } glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); program.setModelMatrix(paddle_left_matrix); program.setViewMatrix(view_matrix); program.setProjectionMatrix(projection_matrix); glUseProgram(program.programID); float texture_coords[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; // global texture coordinates // left paddle float paddle_left_coords[] = { -3.5f, -0.5f, -3.4f, -0.5f, -3.4f, 0.5f, -3.4f, 0.5f, -3.5f, 0.5f, -3.5f, -0.5f }; glVertexAttribPointer(program.positionAttribute, 2, GL_FLOAT, false, 0, paddle_left_coords); glEnableVertexAttribArray(program.positionAttribute); glDrawArrays(GL_TRIANGLES, 0, 6); glVertexAttribPointer(program.texCoordAttribute, 2, GL_FLOAT, false, 0, texture_coords); glEnableVertexAttribArray(program.texCoordAttribute); glBindTexture(GL_TEXTURE_2D, chartreuse_texture_ID); glDisableVertexAttribArray(program.positionAttribute); glDisableVertexAttribArray(program.texCoordAttribute); // right paddle program.setModelMatrix(paddle_right_matrix); float paddle_right_coords[] = { 3.4f, -0.5f, 3.5f, -0.5f, 3.5f, 0.5f, 3.5f, 0.5f, 3.4f, 0.5f, 3.4f, -0.5f }; glVertexAttribPointer(program.positionAttribute, 2, GL_FLOAT, false, 0, paddle_right_coords); glEnableVertexAttribArray(program.positionAttribute); glDrawArrays(GL_TRIANGLES, 0, 6); glVertexAttribPointer(program.texCoordAttribute, 2, GL_FLOAT, false, 0, texture_coords); glEnableVertexAttribArray(program.texCoordAttribute); glBindTexture(GL_TEXTURE_2D, chartreuse_texture_ID); glDisableVertexAttribArray(program.positionAttribute); glDisableVertexAttribArray(program.texCoordAttribute); // ball program.setModelMatrix(ball_matrix); float ball_coords[] = { -0.1f, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 0.1f, 0.1f, -0.1f, 0.1f, -0.1f, -0.1f }; glVertexAttribPointer(program.positionAttribute, 2, GL_FLOAT, false, 0, ball_coords); glEnableVertexAttribArray(program.positionAttribute); glDrawArrays(GL_TRIANGLES, 0, 6); glVertexAttribPointer(program.texCoordAttribute, 2, GL_FLOAT, false, 0, texture_coords); glEnableVertexAttribArray(program.texCoordAttribute); glBindTexture(GL_TEXTURE_2D, chartreuse_texture_ID); glDisableVertexAttribArray(program.positionAttribute); glDisableVertexAttribArray(program.texCoordAttribute); if (game_started) { // right wins if (ball.position_x - 0.1f <= paddle_left.left) { game_started = false; ball_matrix.Translate(-ball.position_x, -ball.position_y, 0.0f); ball.position_x = 0.0f; // for some reason reset() doesn't work :-( ball.position_y = 0.0f; ball.direction_x = (float)rand() / (float)RAND_MAX; ball.direction_y = (float)rand() / (float)RAND_MAX; ball.speed = 0.05f; std::cout << "Right player wins!\n"; } // left wins else if (ball.position_x + 0.1f >= paddle_right.right) { game_started = false; ball_matrix.Translate(-ball.position_x, -ball.position_y, 0.0f); ball.position_x = 0.0f; ball.position_y = 0.0f; ball.direction_x = (float)rand() / (float)RAND_MAX; ball.direction_y = (float)rand() / (float)RAND_MAX; ball.speed = 0.05f; std::cout << "Left player wins!\n"; } // hits top or bottom of screen else if (ball.position_y + 0.1f >= 2.0f || ball.position_y - 0.1f <= -2.0f) { ball.direction_y *= -1; ball.speed += ball.acceleration; ball.move(); ball_matrix.Translate(ball.speed * ball.direction_x, ball.speed * ball.direction_y, 0.0f); } // hits a paddle else if ((ball.position_x - 0.1f <= paddle_left.right && ball.position_y - 0.1f <= paddle_left.top && ball.position_y + 0.1f >= paddle_left.bottom) || (ball.position_x + 0.1f >= paddle_right.left && ball.position_y - 0.1f <= paddle_right.top && ball.position_y + 0.1f >= paddle_right.bottom)) { ball.direction_x *= -1; ball.speed += ball.acceleration; ball.move(); ball_matrix.Translate((ball.speed * ball.direction_x), (ball.speed * ball.direction_y), 0.0f); } // general movement else { ball.move(); ball_matrix.Translate((ball.speed * ball.direction_x), (ball.speed * ball.direction_y), 0.0f); } } SDL_GL_SwapWindow(displayWindow); } SDL_Quit(); return 0; }
// Here is where the real meat of the OSD setup happens. The mesh topology is // created and stored for later use. Actual subdivision happens in updateGeom // which gets called at the end of this function and on frame change. // void createOsdContext(int level) { // // Setup an OsdHbr mesh based on the desired subdivision scheme // static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark; OsdHbrMesh *hmesh(new OsdHbrMesh(&_catmark)); // // Now that we have a mesh, we need to add verticies and define the topology. // Here, we've declared the raw vertex data in-line, for simplicity // float verts[] = { 0.000000f, -1.414214f, 1.000000f, 1.414214f, 0.000000f, 1.000000f, -1.414214f, 0.000000f, 1.000000f, 0.000000f, 1.414214f, 1.000000f, -1.414214f, 0.000000f, -1.000000f, 0.000000f, 1.414214f, -1.000000f, 0.000000f, -1.414214f, -1.000000f, 1.414214f, 0.000000f, -1.000000f }; // // The cube faces are also in-lined, here they are specified as quads // int faces[] = { 0,1,3,2, 2,3,5,4, 4,5,7,6, 6,7,1,0, 1,7,5,3, 6,0,2,4 }; // // Record the original vertex positions and add verts to the mesh. // // OsdVertex is really just a place holder, it doesn't care what the // position of the vertex is, it's just being used here as a means of // defining the mesh topology. // for (unsigned i = 0; i < sizeof(verts)/sizeof(float); i += 3) { g_orgPositions.push_back(verts[i+0]); g_orgPositions.push_back(verts[i+1]); g_orgPositions.push_back(verts[i+2]); OpenSubdiv::OsdVertex vert; hmesh->NewVertex(i/3, vert); } // // Now specify the actual mesh topology by processing the faces array // const unsigned VERTS_PER_FACE = 4; for (unsigned i = 0; i < sizeof(faces)/sizeof(int); i += VERTS_PER_FACE) { // // Do some sanity checking. It is a good idea to keep this in your // code for your personal sanity as well. // // Note that this loop is not changing the HbrMesh, it's purely validating // the topology that is about to be created below. // for (unsigned j = 0; j < VERTS_PER_FACE; j++) { OsdHbrVertex * origin = hmesh->GetVertex(faces[i+j]); OsdHbrVertex * destination = hmesh->GetVertex(faces[i+((j+1)%VERTS_PER_FACE)]); OsdHbrHalfedge * opposite = destination->GetEdge(origin); if(origin==NULL || destination==NULL) { std::cerr << " An edge was specified that connected a nonexistent vertex" << std::endl; exit(1); } if(origin == destination) { std::cerr << " An edge was specified that connected a vertex to itself" << std::endl; exit(1); } if(opposite && opposite->GetOpposite() ) { std::cerr << " A non-manifold edge incident to more than 2 faces was found" << std::endl; exit(1); } if(origin->GetEdge(destination)) { std::cerr << " An edge connecting two vertices was specified more than once." " It's likely that an incident face was flipped" << std::endl; exit(1); } } // // Now, create current face given the number of verts per face and the // face index data. // /* OsdHbrFace * face = */ hmesh->NewFace(VERTS_PER_FACE, faces+i, 0); // // If you had ptex data, you would set it here, for example // /* face->SetPtexIndex(ptexIndex) */ } // // Apply some tags to drive the subdivision algorithm. Here we set the // default boundary interpolation mode along with a corner sharpness. See // the API and the renderman spec for the full list of available operations. // hmesh->SetInterpolateBoundaryMethod( OsdHbrMesh::k_InterpolateBoundaryEdgeOnly ); OsdHbrVertex * v = hmesh->GetVertex(0); v->SetSharpness(2.7f); // // Finalize the mesh object. The Finish() call is a signal to the internals // that optimizations can be made on the mesh data. // hmesh->Finish(); // // Setup some raw vectors of data. Remember that the actual point values were // not stored in the OsdVertex, so we keep track of them here instead // g_normals.resize(g_orgPositions.size(),0.0f); calcNormals( hmesh, g_orgPositions, g_normals ); // // At this point, we no longer need the topological structure of the mesh, // so we bake it down into subdivision tables by converting the HBR mesh // into an OSD mesh. Note that this is just storing the initial subdivision // tables, which will be used later during the actual subdivision process. // // Again, no vertex positions are being stored here, the point data will be // sent to the mesh in updateGeom(). // OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> meshFactory(hmesh, level); g_farmesh = meshFactory.Create(); g_osdComputeContext = OpenSubdiv::OsdCpuComputeContext::Create(g_farmesh); delete hmesh; // // Initialize draw context and vertex buffer // g_vertexBuffer = OpenSubdiv::OsdCpuGLVertexBuffer::Create(6, /* 3 floats for position, + 3 floats for normal*/ g_farmesh->GetNumVertices()); g_drawContext = OpenSubdiv::OsdGLDrawContext::Create(g_farmesh, g_vertexBuffer); // // Setup camera positioning based on object bounds. This really has nothing // to do with OSD. // computeCenterAndSize(g_orgPositions, g_center, &g_size); // // Finally, make an explicit call to updateGeom() to force creation of the // initial buffer objects for the first draw call. // updateGeom(); // // The OsdVertexBuffer provides GL identifiers which can be bound in the // standard way. Here we setup a single VAO and enable points and normals // as attributes on the vertex buffer and set the index buffer. // GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->BindVBO()); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_drawContext->patchIndexBuffer); glBindBuffer(GL_ARRAY_BUFFER, 0); }
void CStatMeshInstance::Draw(unsigned flags) { guard(CStatMeshInstance::Draw); int i; if (!pMesh->Lods.Num()) return; /*const*/ CStaticMeshLod& Mesh = pMesh->Lods[LodNum]; //?? not 'const' because of BuildTangents(); change this? int NumSections = Mesh.Sections.Num(); if (!NumSections || !Mesh.NumVerts) return; // if (!Mesh.HasNormals) Mesh.BuildNormals(); if (!Mesh.HasTangents) Mesh.BuildTangents(); // copy of CSkelMeshInstance::Draw sorting code #if SORT_BY_OPACITY // sort sections by material opacity int SectionMap[MAX_MESHMATERIALS]; int secPlace = 0; for (int opacity = 0; opacity < 2; opacity++) { for (i = 0; i < NumSections; i++) { UUnrealMaterial *Mat = Mesh.Sections[i].Material; int op = 0; // sort value if (Mat && Mat->IsTranslucent()) op = 1; if (op == opacity) SectionMap[secPlace++] = i; } } assert(secPlace == NumSections); #endif // SORT_BY_OPACITY // draw mesh glEnable(GL_LIGHTING); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Position); glNormalPointer(GL_BYTE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Normal); if (UVIndex == 0) { glTexCoordPointer(2, GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].UV.U); } else { glTexCoordPointer(2, GL_FLOAT, sizeof(CMeshUVFloat), &Mesh.ExtraUV[UVIndex-1][0].U); } /*?? Can move tangent/binormal setup here too, but this will require to force shader to use fixed attribute locations (use glBindAttribLocation before glLinkProgram instead of querying atttribute via glGetAtribLocation). In this case: - can remove GCurrentShader - can eliminate hasTangent checks below and always bind attributes (when supports GL2.0) - can share code between SkeletalMesh and StaticMesh: - sort sections - setup arrays; differences: - position and normals are taken from different arrays in static and skeletal meshes - ShowInfluences in SkeletalMeshInstance should disable material binding - draw sections using glDrawElements() - un-setup arrays - use VAO+VBO for rendering */ for (i = 0; i < NumSections; i++) { #if SORT_BY_OPACITY int MaterialIndex = SectionMap[i]; #else int MaterialIndex = i; #endif const CMeshSection &Sec = Mesh.Sections[MaterialIndex]; if (!Sec.NumFaces) continue; SetMaterial(Sec.Material, MaterialIndex); // check tangent space GLint aNormal = -1; GLint aTangent = -1; // GLint aBinormal = -1; const CShader *Sh = GCurrentShader; if (Sh) { aNormal = Sh->GetAttrib("normal"); aTangent = Sh->GetAttrib("tangent"); // aBinormal = Sh->GetAttrib("binormal"); } if (aNormal >= 0) { glEnableVertexAttribArray(aNormal); // send 4 components to decode binormal in shader glVertexAttribPointer(aNormal, 4, GL_BYTE, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Normal); } if (aTangent >= 0) { glEnableVertexAttribArray(aTangent); glVertexAttribPointer(aTangent, 3, GL_BYTE, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Tangent); } /* if (aBinormal >= 0) { glEnableVertexAttribArray(aBinormal); glVertexAttribPointer(aBinormal, 3, GL_BYTE, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Binormal); } */ // draw //?? place this code into CIndexBuffer? if (Mesh.Indices.Is32Bit()) glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_INT, &Mesh.Indices.Indices32[Sec.FirstIndex]); else glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_SHORT, &Mesh.Indices.Indices16[Sec.FirstIndex]); // disable tangents if (aNormal >= 0) glDisableVertexAttribArray(aNormal); if (aTangent >= 0) glDisableVertexAttribArray(aTangent); // if (aBinormal >= 0) // glDisableVertexAttribArray(aBinormal); } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_LIGHTING); BindDefaultMaterial(true); // draw mesh normals if (flags & DF_SHOW_NORMALS) { //!! TODO: performance issues when displaying a large mesh (1M+ triangles) with normals/tangents. //!! Possible solution: //!! 1. use vertex buffer for normals, use single draw call //!! 2. cache normal data between render frames //!! 3. DecodeTangents() will do Unpack() for normal and tangent too, so this work is duplicated here int NumVerts = Mesh.NumVerts; glBegin(GL_LINES); glColor3f(0.5, 1, 0); CVecT tmp, unpacked; const float VisualLength = 2.0f; for (i = 0; i < NumVerts; i++) { glVertex3fv(Mesh.Verts[i].Position.v); Unpack(unpacked, Mesh.Verts[i].Normal); VectorMA(Mesh.Verts[i].Position, VisualLength, unpacked, tmp); glVertex3fv(tmp.v); } #if SHOW_TANGENTS glColor3f(0, 0.5f, 1); for (i = 0; i < NumVerts; i++) { const CVec3 &v = Mesh.Verts[i].Position; glVertex3fv(v.v); Unpack(unpacked, Mesh.Verts[i].Tangent); VectorMA(v, VisualLength, unpacked, tmp); glVertex3fv(tmp.v); } glColor3f(1, 0, 0.5f); for (i = 0; i < NumVerts; i++) { const CMeshVertex& vert = Mesh.Verts[i]; // decode binormal CVecT normal, tangent, binormal; vert.DecodeTangents(normal, tangent, binormal); // render const CVecT &v = vert.Position; glVertex3fv(v.v); VectorMA(v, VisualLength, binormal, tmp); glVertex3fv(tmp.v); } #endif // SHOW_TANGENTS glEnd(); } unguard; }
void RiftAppSkeleton::display_client() //const { ovrHmd hmd = m_Hmd; if (hmd == NULL) return; //ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrameTiming(hmd, 0); bindFBO(m_renderBuffer, m_fboScale); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { const ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; const ovrPosef eyePose = ovrHmd_GetEyePose(hmd, eye); m_eyeOri = eyePose.Orientation; // cache this for movement direction _StoreHmdPose(eyePose); const ovrGLTexture& otex = l_EyeTexture[eye]; const ovrRecti& rvp = otex.OGL.Header.RenderViewport; const ovrRecti rsc = { static_cast<int>(m_fboScale * rvp.Pos.x), static_cast<int>(m_fboScale * rvp.Pos.y), static_cast<int>(m_fboScale * rvp.Size.w), static_cast<int>(m_fboScale * rvp.Size.h) }; glViewport(rsc.Pos.x, rsc.Pos.y, rsc.Size.w, rsc.Size.h); const OVR::Matrix4f proj = ovrMatrix4f_Projection( m_EyeRenderDesc[eye].Fov, 0.01f, 10000.0f, true); ///@todo Should we be using this variable? //m_EyeRenderDesc[eye].DistortedViewport; const OVR::Matrix4f view = _MakeModelviewMatrix( eyePose, m_EyeRenderDesc[eye].ViewAdjust, m_chassisYaw, m_chassisPos); const OVR::Matrix4f scaledView = _MakeModelviewMatrix( eyePose, m_EyeRenderDesc[eye].ViewAdjust, m_chassisYaw, m_chassisPos, m_headSize); _resetGLState(); _DrawScenes(&view.Transposed().M[0][0], &proj.Transposed().M[0][0], rsc, &scaledView.Transposed().M[0][0]); } unbindFBO(); // Set full viewport...? const int w = m_Cfg.OGL.Header.RTSize.w; const int h = m_Cfg.OGL.Header.RTSize.h; glViewport(0, 0, w, h); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Now draw the distortion mesh... for(int eyeNum = 0; eyeNum < 2; eyeNum++) { const ShaderWithVariables& eyeShader = eyeNum == 0 ? m_presentDistMeshL : m_presentDistMeshR; const GLuint prog = eyeShader.prog(); glUseProgram(prog); //glBindVertexArray(eyeShader.m_vao); { const ovrDistortionMesh& mesh = m_DistMeshes[eyeNum]; glBindBuffer(GL_ARRAY_BUFFER, 0); const int a_pos = glGetAttribLocation(prog, "vPosition"); glVertexAttribPointer(a_pos, 4, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].ScreenPosNDC.x); glEnableVertexAttribArray(a_pos); const int a_texR = glGetAttribLocation(prog, "vTexR"); if (a_texR > -1) { glVertexAttribPointer(a_texR, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].TanEyeAnglesR); glEnableVertexAttribArray(a_texR); } const int a_texG = glGetAttribLocation(prog, "vTexG"); if (a_texG > -1) { glVertexAttribPointer(a_texG, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].TanEyeAnglesG); glEnableVertexAttribArray(a_texG); } const int a_texB = glGetAttribLocation(prog, "vTexB"); if (a_texB > -1) { glVertexAttribPointer(a_texB, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].TanEyeAnglesB); glEnableVertexAttribArray(a_texB); } ovrVector2f uvoff = m_uvScaleOffsetOut[2*eyeNum + 1]; //DistortionData.UVScaleOffset[eyeNum][0]; ovrVector2f uvscale = m_uvScaleOffsetOut[2*eyeNum + 0]; //DistortionData.UVScaleOffset[eyeNum][1]; glUniform2f(eyeShader.GetUniLoc("EyeToSourceUVOffset"), uvoff.x, uvoff.y); glUniform2f(eyeShader.GetUniLoc("EyeToSourceUVScale"), uvscale.x, uvscale.y); #if 0 // Setup shader constants DistortionData.Shaders->SetUniform2f( "EyeToSourceUVScale", DistortionData.UVScaleOffset[eyeNum][0].x, DistortionData.UVScaleOffset[eyeNum][0].y); DistortionData.Shaders->SetUniform2f( "EyeToSourceUVOffset", DistortionData.UVScaleOffset[eyeNum][1].x, DistortionData.UVScaleOffset[eyeNum][1].y); if (distortionCaps & ovrDistortionCap_TimeWarp) { // TIMEWARP - Additional shader constants required ovrMatrix4f timeWarpMatrices[2]; ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, eyeRenderPoses[eyeNum], timeWarpMatrices); //WARNING!!! These matrices are transposed in SetUniform4x4f, before being used by the shader. DistortionData.Shaders->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0])); DistortionData.Shaders->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1])); } // Perform distortion pRender->Render( &distortionShaderFill, DistortionData.MeshVBs[eyeNum], DistortionData.MeshIBs[eyeNum]); #endif glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_renderBuffer.tex); glUniform1i(eyeShader.GetUniLoc("fboTex"), 0); // This is the only uniform that changes per-frame glUniform1f(eyeShader.GetUniLoc("fboScale"), m_fboScale); glDrawElements( GL_TRIANGLES, mesh.IndexCount, GL_UNSIGNED_SHORT, &mesh.pIndexData[0]); } glBindVertexArray(0); glUseProgram(0); } ovrHmd_EndFrameTiming(hmd); }
//-------------------------------------------------------------- // render the planet void Planet::render( int graphicsWidth, int graphicsHeight, double angle) { // if shader didn't compile, nothing we can do if (m_planetShader == 0) return; double atmos = 20.0; double radius = 1200.0; double eyeDist = m_eyePt.length()/radius; double a = 1.0; if (eyeDist < a) return; // below surface, nothing to do double b = sqrt(eyeDist*eyeDist - a*a); double h = (a*b)/eyeDist; double m = (a*a)/eyeDist; h += atmos/radius; // x axis from planet center towards eye mgPoint3 xaxis(m_eyePt); xaxis.normalize(); // build y axis mgPoint3 yaxis(xaxis); yaxis.cross(mgPoint3(0.0, 1.0, 0.0)); yaxis.normalize(); mgPoint3 zaxis(yaxis); zaxis.cross(xaxis); zaxis.normalize(); mgMatrix4 transform; transform._11 = xaxis.x; transform._12 = xaxis.y; transform._13 = xaxis.z; transform._21 = yaxis.x; transform._22 = yaxis.y; transform._23 = yaxis.z; transform._31 = zaxis.x; transform._32 = zaxis.y; transform._33 = zaxis.z; VertexPlanet tl, tr, bl, br; mgPoint3 pt; transform.mapPt(m, -h, h, pt.x, pt.y, pt.z); tl.setPoint(radius*pt.x, radius*pt.y, radius*pt.z); transform.mapPt(m, h, h, pt.x, pt.y, pt.z); tr.setPoint(radius*pt.x, radius*pt.y, radius*pt.z); transform.mapPt(m, -h, -h, pt.x, pt.y, pt.z); bl.setPoint(radius*pt.x, radius*pt.y, radius*pt.z); transform.mapPt(m, h, -h, pt.x, pt.y, pt.z); br.setPoint(radius*pt.x, radius*pt.y, radius*pt.z); // inverse of world transform mgMatrix4 model; model.rotateYDeg(-angle); mgPoint3 lightDir(1.0, 0.25, 0.0); lightDir.normalize(); mgPoint3 modelLightDir; model.mapPt(lightDir, modelLightDir); transform.multiply(model); mgPoint3 modelEye; transform.mapPt(eyeDist, 0.0, 0.0, modelEye.x, modelEye.y, modelEye.z); transform.mapPt(m, -h, h, pt.x, pt.y, pt.z); tl.setModelPoint(pt.x, pt.y, pt.z); transform.mapPt(m, h, h, pt.x, pt.y, pt.z); tr.setModelPoint(pt.x, pt.y, pt.z); transform.mapPt(m, -h, -h, pt.x, pt.y, pt.z); bl.setModelPoint(pt.x, pt.y, pt.z); transform.mapPt(m, h, -h, pt.x, pt.y, pt.z); br.setModelPoint(pt.x, pt.y, pt.z); mgMatrix4 viewMatrix; viewMatrix.translate(-m_eyePt.x, -m_eyePt.y, -m_eyePt.z); viewMatrix.multiply(m_eyeMatrix); mgMatrix4 worldProjection; createProjection(worldProjection, graphicsWidth, graphicsHeight); mgMatrix4 mvpMatrix(viewMatrix); mvpMatrix.multiply(worldProjection); setupShader(mvpMatrix, modelEye, modelLightDir); glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, m_surfaceTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, m_cloudsTexture); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPlanet), (const GLvoid*) offsetof(VertexPlanet, m_px)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPlanet), (const GLvoid*) offsetof(VertexPlanet, m_mx)); VertexPlanet data[6]; data[0] = tl; data[1] = tr; data[2] = bl; data[3] = bl; data[4] = tr; data[5] = br; int vertexSize = sizeof(VertexPlanet); int count = 6; glBufferData(GL_ARRAY_BUFFER, vertexSize * count, data, GL_DYNAMIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, count); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); glActiveTexture(GL_TEXTURE0); }
bool Mesh::InitFromScene(const aiScene* pScene, const string& Filename) { m_Entries.resize(pScene->mNumMeshes); m_Textures.resize(pScene->mNumMaterials); vector<Vector3f> Positions; vector<Vector3f> Normals; vector<Vector2f> TexCoords; vector<VertexBoneData> Bones; vector<uint> Indices; uint NumVertices = 0; uint NumIndices = 0; uint VerticesPerPrim = m_withAdjacencies ? 6 : 3; // Count the number of vertices and indices for (uint i = 0 ; i < m_Entries.size() ; i++) { m_Entries[i].MaterialIndex = pScene->mMeshes[i]->mMaterialIndex; m_Entries[i].NumIndices = pScene->mMeshes[i]->mNumFaces * VerticesPerPrim; m_Entries[i].BaseVertex = NumVertices; m_Entries[i].BaseIndex = NumIndices; NumVertices += pScene->mMeshes[i]->mNumVertices; NumIndices += m_Entries[i].NumIndices; } // Reserve space in the vectors for the vertex attributes and indices Positions.reserve(NumVertices); Normals.reserve(NumVertices); TexCoords.reserve(NumVertices); Bones.resize(NumVertices); Indices.reserve(NumIndices); // Initialize the meshes in the scene one by one for (uint i = 0 ; i < m_Entries.size() ; i++) { const aiMesh* paiMesh = pScene->mMeshes[i]; InitMesh(i, paiMesh, Positions, Normals, TexCoords, Bones, Indices); } if (!InitMaterials(pScene, Filename)) { return false; } // Generate and populate the buffers with vertex attributes and the indices glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[POS_VB]); glBufferData(GL_ARRAY_BUFFER, sizeof(Positions[0]) * Positions.size(), &Positions[0], GL_STATIC_DRAW); glEnableVertexAttribArray(POSITION_LOCATION); glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[TEXCOORD_VB]); glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords[0]) * TexCoords.size(), &TexCoords[0], GL_STATIC_DRAW); glEnableVertexAttribArray(TEX_COORD_LOCATION); glVertexAttribPointer(TEX_COORD_LOCATION, 2, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[NORMAL_VB]); glBufferData(GL_ARRAY_BUFFER, sizeof(Normals[0]) * Normals.size(), &Normals[0], GL_STATIC_DRAW); glEnableVertexAttribArray(NORMAL_LOCATION); glVertexAttribPointer(NORMAL_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[BONE_VB]); glBufferData(GL_ARRAY_BUFFER, sizeof(Bones[0]) * Bones.size(), &Bones[0], GL_STATIC_DRAW); glEnableVertexAttribArray(BONE_ID_LOCATION); glVertexAttribIPointer(BONE_ID_LOCATION, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0); glEnableVertexAttribArray(BONE_WEIGHT_LOCATION); glVertexAttribPointer(BONE_WEIGHT_LOCATION, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)16); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Buffers[INDEX_BUFFER]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices[0]) * Indices.size(), &Indices[0], GL_STATIC_DRAW); return GLCheckError(); }
int main(int argc, char** argv) { if (!glfwInit()) // 初始化glfw库 { std::cout << "Error::GLFW could not initialize GLFW!" << std::endl; return -1; } // 开启OpenGL 3.3 core profile std::cout << "Start OpenGL core profile version 3.3" << std::endl; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); glfwWindowHint(GLFW_SAMPLES, 4); // 设置采样点个数 注意这里设置GLFW选项 不要写成了GL_SAMPLES // 创建窗口 GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo of anti-aliasing(press O on, F off)", NULL, NULL); if (!window) { std::cout << "Error::GLFW could not create winddow!" << std::endl; glfwTerminate(); std::system("pause"); return -1; } // 创建的窗口的context指定为当前context glfwMakeContextCurrent(window); // 注册窗口键盘事件回调函数 glfwSetKeyCallback(window, key_callback); // 注册鼠标事件回调函数 glfwSetCursorPosCallback(window, mouse_move_callback); // 注册鼠标滚轮事件回调函数 glfwSetScrollCallback(window, mouse_scroll_callback); // 鼠标捕获 停留在程序内 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // 初始化GLEW 获取OpenGL函数 glewExperimental = GL_TRUE; // 让glew获取所有拓展函数 GLenum status = glewInit(); if (status != GLEW_OK) { std::cout << "Error::GLEW glew version:" << glewGetString(GLEW_VERSION) << " error string:" << glewGetErrorString(status) << std::endl; glfwTerminate(); std::system("pause"); return -1; } // 设置视口参数 glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); //Section1 顶点属性数据 // 指定立方体顶点属性数据 顶点位置 纹理 GLfloat cubeVertices[] = { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // A 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // B 0.5f, 0.5f, 0.5f,1.0f, 1.0f, // C 0.5f, 0.5f, 0.5f,1.0f, 1.0f, // C -0.5f, 0.5f, 0.5f,0.0f, 1.0f, // D -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A -0.5f, -0.5f, -0.5f,0.0f, 0.0f, // E -0.5f, 0.5f, -0.5f,0.0, 1.0f, // H 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G 0.5f, -0.5f, -0.5f,1.0f, 0.0f, // F -0.5f, -0.5f, -0.5f,0.0f, 0.0f, // E -0.5f, 0.5f, 0.5f,0.0f, 1.0f, // D -0.5f, 0.5f, -0.5f,1.0, 1.0f, // H -0.5f, -0.5f, -0.5f,1.0f, 0.0f, // E -0.5f, -0.5f, -0.5f,1.0f, 0.0f, // E -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A -0.5f, 0.5f, 0.5f,0.0f, 1.0f, // D 0.5f, -0.5f, -0.5f,1.0f, 0.0f, // F 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G 0.5f, 0.5f, 0.5f,0.0f, 1.0f, // C 0.5f, 0.5f, 0.5f,0.0f, 1.0f, // C 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // B 0.5f, -0.5f, -0.5f,1.0f, 0.0f, // F 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G -0.5f, 0.5f, -0.5f,0.0, 1.0f, // H -0.5f, 0.5f, 0.5f,0.0f, 0.0f, // D -0.5f, 0.5f, 0.5f,0.0f, 0.0f, // D 0.5f, 0.5f, 0.5f,1.0f, 0.0f, // C 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,// E 0.5f, -0.5f, -0.5f,1.0f, 1.0f, // F 0.5f, -0.5f, -0.5f,1.0f, 1.0f, // F 0.5f, -0.5f, 0.5f,1.0f, 0.0f, // B -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A }; // Section2 准备缓存对象 GLuint cubeVAOId, cubeVBOId; glGenVertexArrays(1, &cubeVAOId); glGenBuffers(1, &cubeVBOId); glBindVertexArray(cubeVAOId); glBindBuffer(GL_ARRAY_BUFFER, cubeVBOId); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW); // 顶点位置数据 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (GLvoid*)0); glEnableVertexAttribArray(0); // 顶点纹理数据 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (GLvoid*)(3 * sizeof(GL_FLOAT))); glEnableVertexAttribArray(1); glBindVertexArray(0); // Section3 准备着色器程序 Shader shader("scene.vertex", "scene.frag"); glEnable(GL_MULTISAMPLE); // 开启multisample glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); // 开始游戏主循环 while (!glfwWindowShouldClose(window)) { GLfloat currentFrame = (GLfloat)glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); // 处理例如鼠标 键盘等事件 do_movement(); // 根据用户操作情况 更新相机属性 glClearColor(0.18f, 0.04f, 0.14f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); glm::mat4 projection = glm::perspective(camera.mouse_zoom, (GLfloat)(WINDOW_WIDTH) / WINDOW_HEIGHT, 1.0f, 100.0f); // 投影矩阵 glm::mat4 view = camera.getViewMatrix(); // 视变换矩阵 glUniformMatrix4fv(glGetUniformLocation(shader.programId, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shader.programId, "view"), 1, GL_FALSE, glm::value_ptr(view)); glm::mat4 model; model = glm::mat4(); model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(glGetUniformLocation(shader.programId, "model"), 1, GL_FALSE, glm::value_ptr(model)); // 这里填写场景绘制代码 glBindVertexArray(cubeVAOId); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); glBindVertexArray(0); glUseProgram(0); glfwSwapBuffers(window); // 交换缓存 } // 释放资源 glDeleteVertexArrays(1, &cubeVAOId); glDeleteBuffers(1, &cubeVBOId); glfwTerminate(); return 0; }
void Renderer::render( Scene* toRender ) { glClearColor(1.0f,0.8f,0.8f,1.0f); Program::checkGLErrors( "glClearColor" ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Program::checkGLErrors( "glClear" ); glm::mat4 mv, mvp; glm::mat3 rot, normal; ModelData data; Model model; Material mat; Program* shader; std::vector<DisplayObject> objects = toRender->getDisplayObjects(); for(int i = 0; i < objects.size(); i++) { model = objects[i].getModel(); for(int j = 0; j < model.numMeshes(); j++) { //Doesn't work ;_; //mat = *(objects[i].getMaterial( model.getMeshInfo(j).matIndex )); if(objects[i].customMatAvailable) mat = (objects[i].getMaterial(0)); else mat = model.materials[ model.getMeshInfo(j).matIndex ]; shader = mat.shader; setActiveProgram( shader ); Program::checkGLErrors( "Setting active program" ); glBindVertexArray( model.getVAO( j ) ); Program::checkGLErrors("Binding vertex array"); glBindTexture( GL_TEXTURE_2D, mat.texDiffuse ); Program::checkGLErrors( "Binding texture" ); //Update uniforms just loads the constant uniforms, e.g. Ld and stuff. updateUniforms( objects[i] ); glDrawElements(GL_TRIANGLES, model.getMeshInfo(j).numIndices, GL_UNSIGNED_INT, NULL); if( objects[i].renderBoundingBox ) { setActiveProgram( simplePr ); glBindVertexArray( bBoxVao ); glBindTexture( GL_TEXTURE_2D, 0 ); glBindBuffer( GL_ARRAY_BUFFER, model.getMeshInfo( j ).boundingBoxBuffer ); //When you finally fix updateUniforms such that it isn't horrible, make sure to give a way to only send the mvp matrix in, so we can delete this line glm::mat4 mv = projection * (camera * objects[i].getTransform()); glUniformMatrix4fv(activeProgram->getUniform("mvp"), 1, GL_FALSE, glm::value_ptr(mv) ); glVertexAttribPointer( simplePr->getAttrib("theV"),3,GL_FLOAT,0,0,0); glEnableVertexAttribArray(simplePr->getAttrib("theV")); glDrawElements(GL_LINE_STRIP,20, GL_UNSIGNED_INT, NULL); } } glBindVertexArray( 0 ); glBindTexture( GL_TEXTURE_2D, 0 ); setActiveProgram( 0 ); } glFlush(); Program::checkGLErrors("Post render"); }