Ejemplo n.º 1
0
// gets called every frame to draw the scene
void CRenderer::Update(const float dt, const uint32_t ticks)
{
    CObj* obj, *localctrl;
    int localctrlid;
    OBJITER iter;
    matrix_t m;
    vec3_t dir, up, side;
    CFrustum frustum;
    CWorld* world;

    localctrl = m_world->GetLocalController();
    localctrlid = m_world->GetLocalObj()->GetID();
    world = m_world->GetInterpWorld();

    const vec3_t campos = localctrl->GetOrigin();
    const quaternion_t camrot = localctrl->GetRot();

    m.SetCamTransform(campos, camrot);
    m.GetVec3Cam(&dir, &up, &side);
    dir = -dir;
    frustum.Setup(campos, dir, up, side,
                  RENDERER_FOV, (float)m_width/(float)m_height,
                  PLANE_NEAR,
                  PLANE_FAR);

    // light floating above the players head
    const vec3_t lightpos0(campos + vec3_t(0,25.0f,0));
    const quaternion_t lightrot0(quaternion_t(vec3_t::xAxis, -90.0f*lynxmath::DEGTORAD));
    const float lightpos0_4f[4] = {lightpos0.x, lightpos0.y, lightpos0.z, 1};
    glLightfv(GL_LIGHT0, GL_POSITION, lightpos0_4f);
    if(m_shaderactive)
    {
        if(m_useShadows)
        {
            glUseProgram(0); // draw shadowmap with fixed function pipeline
            PrepareShadowMap(lightpos0,
                    lightrot0,
                    world,
                    localctrlid); // the player is the light
        }
        glUseProgram(m_program); // activate shader
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(m.pm);

    glClear(GL_DEPTH_BUFFER_BIT);
    glClear(GL_COLOR_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0); // normal texture channel

    if(m_shaderactive)
    {
        glUniform1i(m_tex, 0); // good old textures: GL_TEXTURE0
        glUniform1i(m_normalMap, 1); // normal maps are GL_TEXTURE1
        glUniform1i(m_lightmap, 2); // lightmap

        if(m_useShadows)
        {
            glUniform1i(m_shadowMapUniform, 7);
            glActiveTexture(GL_TEXTURE7); // shadow mapping texture GL_TEXTURE7
            glBindTexture(GL_TEXTURE_2D, m_depthTextureId);
            glActiveTexture(GL_TEXTURE0);
        }

#ifdef DRAW_NORMALS
        glUseProgram(0); // use fixed pipeline for this debug mode
#endif
    }

    // Main drawing
    DrawScene(frustum, world, localctrlid, false);

    if(m_shaderactive)
        glUseProgram(0); // don't use shader for particles

    // Particle Draw
    glDisable(GL_LIGHTING);
    glDepthMask(false);
    for(iter=world->ObjBegin();iter!=world->ObjEnd();++iter)
    {
        obj = (*iter).second;

        if(obj->GetMesh())
        {
            // Animate mesh is done in the particle loop
            // and not in DrawScene, because DrawScene
            // can be called multiple times per frame
            obj->GetMesh()->Animate(obj->GetMeshState(), dt);
        }

        if(obj->GetID() == localctrlid || !obj->GetParticleSystem())
            continue;

        // Update/animate the particles, depending on dt and the current position.
        obj->GetParticleSystem()->Update(dt, ticks, obj->GetOrigin());

        // Draw the particles. FIXME: this should use a frustum test
        obj->GetParticleSystem()->Render(side, up, dir);
    }
    glDepthMask(true);
    glColor4f(1,1,1,1);
    glEnable(GL_LIGHTING);

#ifdef DRAW_NORMALS
    // Draw vertex normals of level geometry (not face normals)
    if(world && world->GetBSP())
    {
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_LIGHTING);
        world->GetBSP()->RenderNormals();
        glEnable(GL_LIGHTING);
        glEnable(GL_DEPTH_TEST);
    }
#endif

    // Draw weapon
    if(m_shaderactive) // use shader for weapon
        glUseProgram(m_program);

    CModelMD5* viewmodel;
    md5_state_t* viewmodelstate;
    m_world->m_hud.GetModel(&viewmodel, &viewmodelstate);
    glDisable(GL_LIGHTING);
    if(viewmodel)
    {
        glClear(GL_DEPTH_BUFFER_BIT);
        glPushMatrix();
          glLoadIdentity();
          viewmodel->Render(viewmodelstate);
          viewmodel->Animate(viewmodelstate, dt);
        glPopMatrix();
    }
    glEnable(GL_LIGHTING);

    // Draw HUD
    if(m_shaderactive)
        glUseProgram(0); // no shader for HUD

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0, m_width, m_height, 0, 0, 1);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glColor4f(1,1,1,1);
    glBindTexture(GL_TEXTURE_2D, m_crosshair);

    // Draw center crosshair
    glBegin(GL_QUADS);
        glTexCoord2d(0,1);
        glVertex3f((m_width-m_crosshair_width)*0.5f, (m_height-m_crosshair_height)*0.5f,0.0f);
        glTexCoord2d(0,0);
        glVertex3f((m_width-m_crosshair_width)*0.5f, (m_height+m_crosshair_height)*0.5f,0.0f);
        glTexCoord2d(1,0);
        glVertex3f((m_width+m_crosshair_width)*0.5f, (m_height+m_crosshair_height)*0.5f,0.0f);
        glTexCoord2d(1,1);
        glVertex3f((m_width+m_crosshair_width)*0.5f, (m_height-m_crosshair_height)*0.5f,0.0f);
    glEnd();

    // draw HUD text: score, health...
    char hudtextbuf[64];
    sprintf(hudtextbuf, "Frags: %i", m_world->m_hud.score);
    m_font.DrawGL(10.0f, m_height - 30.0f, 0.0f, hudtextbuf);
    sprintf(hudtextbuf, "%i", m_world->m_hud.health);
    m_font.DrawGL(10.0f, m_height - 35.0f - (float)m_font.GetHeight(), 0.0f, hudtextbuf);

#ifdef DRAW_SHADOWMAP // draw a small window with the scene from the light POV
    if(m_shaderactive)
    {
        //glBindTexture(GL_TEXTURE_2D, m_depthTextureId);
        glBindTexture(GL_TEXTURE_2D, g_fboShadowCamColor);
        const float shadowmap_debug_width = 200.0f;
        const float shadowmap_debug_height = shadowmap_debug_width*(float)m_height/(float)m_width;
        glBegin(GL_QUADS);
            glTexCoord2d(0,1); // upper left
            glVertex3f(0.0f, 0.0f, 0.0f);
            glTexCoord2d(0,0); //lower left
            glVertex3f(0.0f, shadowmap_debug_height, 0.0f);
            glTexCoord2d(1,0); //lower right
            glVertex3f(shadowmap_debug_width, shadowmap_debug_height, 0.0f);
            glTexCoord2d(1,1); // upper right
            glVertex3f(shadowmap_debug_width, 0.0f, 0.0f);
        glEnd();
    }
#endif

    glBindTexture(GL_TEXTURE_2D, 0);
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);
}
Ejemplo n.º 2
0
void CRenderer::PrepareShadowMap(const vec3_t& lightpos,
                                 const quaternion_t& lightrot,
                                 CWorld* world, int localctrlid)
{
    CFrustum frustum;
    vec3_t dir, up, side;
    matrix_t mviewlight;
    mviewlight.SetCamTransform(lightpos, lightrot);

    mviewlight.GetVec3Cam(&dir, &up, &side);
    dir = -dir;
    frustum.Setup(lightpos, dir, up, side,
                  RENDERER_FOV, (float)m_width/(float)m_height,
                  PLANE_NEAR,
                  PLANE_FAR);
    glViewport(0, 0, (int)(m_width * SHADOW_MAP_RATIO),
                     (int)(m_height * SHADOW_MAP_RATIO));
    float projection[16];
    glMatrixMode(GL_PROJECTION);
    // Shadow mapping with ortho projection can be useful
    //const float lightDistance = PLANE_FAR*0.1f;
    //glLoadIdentity();
    //glOrtho(-35.0f, 35.0f, -35.0f, 35.0f, 0.0f, PLANE_FAR*0.1f); // dimension: light area in m
    glGetFloatv(GL_PROJECTION_MATRIX, projection);
    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(mviewlight.pm); // set camera to light pos

    glMatrixMode(GL_TEXTURE);
    glActiveTexture(GL_TEXTURE7);
    glLoadMatrixf(g_shadowBias); // to map from -1..1 to 0..1
    glMultMatrixf(projection);
    glMultMatrixf(mviewlight.pm);
    glMatrixMode(GL_MODELVIEW);

    // Render to FBO
    glBindFramebuffer(GL_FRAMEBUFFER, m_fboId);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    glDisable(GL_LIGHTING);
    glDisable(GL_BLEND);
#ifndef DRAW_SHADOWMAP
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
#endif
    //glCullFace(GL_FRONT);
    glPolygonOffset( 1.1f, 4.0f );
    glEnable(GL_POLYGON_OFFSET_FILL);

    DrawScene(frustum, world, localctrlid, true);

    glDisable(GL_POLYGON_OFFSET_FILL);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, m_width, m_height);
#ifndef DRAW_SHADOWMAP
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
#endif
    //glCullFace(GL_BACK);
    glEnable(GL_LIGHTING);
    glEnable(GL_BLEND);

    UpdatePerspective(); // restore standard projection
}