OpenGL:如何在场景中添加阴影贴图?

时间:2014-04-03 14:38:09

标签: opengl shadow

所以我在OpenGL中有一个场景,我使用本网站的教程: http://arcsynthesis.org/gltut/ (不,我不能使用不同的基础)

我需要添加阴影贴图。有人告诉我使用这个网站: http://ogldev.atspace.co.uk/www/tutorial23/tutorial23.html (不,我......可能不会使用不同的网站,虽然我绝望了)

这是我使用的代码:

#include <string>
#include <vector>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <glload/gl_3_3.h>
#include <glutil/glutil.h>
#include <GL/freeglut.h>
#include "../framework/framework.h"
#include "../framework/Mesh.h"
#include "../framework/MousePole.h"
#include "../framework/Timer.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glimg/glimg.h>

#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))

struct ProgramData
{
    GLuint theProgram;

    GLuint modelToCameraMatrixUnif;

    GLuint objectColorUnif;
    GLuint cameraToClipMatrixUnif;

    GLuint lightIntensityUnif;
    GLuint ambientIntensityUnif;

    GLuint normalModelToCameraMatrixUnif;
    GLuint cameraSpaceLightPosUnif;
    GLuint windowSizeUnif;
    GLuint lightAttenuationUnif;
    GLuint bUseRSquareUnif;
    GLuint shininessFactorUnif;
    GLuint numberTextureUnif;
};


float g_fzNear = 1.0f;
float g_fzFar = 1000.0f;

ProgramData g_FragWhiteDiffuseColor;
ProgramData g_FragWhiteDiffuseColortex;

ProgramData LoadLitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
{
    std::vector<GLuint> shaderList;

    shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
    shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));

    ProgramData data;
    data.theProgram = Framework::CreateProgram(shaderList);
    data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");

    data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");

    data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
    data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
    data.shininessFactorUnif = glGetUniformLocation(data.theProgram, "shininessFactor");

    data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
    data.cameraSpaceLightPosUnif = glGetUniformLocation(data.theProgram, "cameraSpaceLightPos");
    data.windowSizeUnif = glGetUniformLocation(data.theProgram, "windowSize");
    data.lightAttenuationUnif = glGetUniformLocation(data.theProgram, "lightAttenuation");
    data.bUseRSquareUnif = glGetUniformLocation(data.theProgram, "bUseRSquare");
    data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");

    data.numberTextureUnif = glGetUniformLocation(data.theProgram, "numberTexture");

    return data;
}

void InitializePrograms()
{
    g_FragWhiteDiffuseColor = LoadLitProgram("FragLightAtten_PCN.vert", "FragLightAtten.frag");
    g_FragWhiteDiffuseColortex = LoadLitProgram("FragLightAtten_PCN.vert", "FragLightAttentex.frag");
}


GLuint g_samplers[1];
GLuint g_textures[5];


Framework::Mesh *g_pCylinderMesh = NULL;
Framework::Mesh *g_pPlaneMesh = NULL; 

void LoadTexture()
{

    glGenSamplers(1, &g_samplers[0]);

    glSamplerParameteri(g_samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glSamplerParameteri(g_samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glSamplerParameteri(g_samplers[0], GL_TEXTURE_WRAP_S, GL_REPEAT);
    glSamplerParameteri(g_samplers[0], GL_TEXTURE_WRAP_T, GL_REPEAT);


    glGenTextures(5, &g_textures[0]);

    //cylinder
    std::string filename(Framework::FindFileOrThrow("13_grass.jpg"));
    std::auto_ptr<glimg::ImageSet> pImageSet(glimg::loaders::stb::LoadFromFile(filename.c_str()));
    glimg::SingleImage image = pImageSet->GetImage(0, 0, 0);
    glimg::Dimensions dims = image.GetDimensions();
    glimg::OpenGLPixelTransferParams pxTrans = glimg::GetUploadFormatType(pImageSet->GetFormat(), 0);
    glBindTexture(GL_TEXTURE_2D, g_textures[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, dims.width, dims.height, 0,
    pxTrans.format, pxTrans.type, image.GetImageData());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);


}



//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
void init()
{
    InitializePrograms();

    try
    {
        g_pCylinderMesh = new Framework::Mesh("UnitCylinder.xml");
        g_pPlaneMesh = new Framework::Mesh("LargePlane.xml");
    }
    catch(std::exception &except)
    {
        printf("%s\n", except.what());
        throw;
    }

    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glFrontFace(GL_CW);

    const float depthZNear = 0.0f;
    const float depthZFar = 1.0f;

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    glDepthRange(depthZNear, depthZFar);
    glEnable(GL_DEPTH_CLAMP);


    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    LoadTexture();
}







static float g_fLightHeight = 1.5f;
static float g_fLightRadius = 1.0f;
static bool g_bUseRSquare = true;

static float g_fLightAttenuation = 1.0f;

float zl=0.0f,xl=4.0f,yl=2.0f;

//calculating the light
 using Framework::Timer;
Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
void CalcLightPosition()
{
    float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();

    glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);

    xl = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
    zl = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;


}

void display()
{
    g_LightTimer.Update();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glutil::MatrixStack persMatrix;
    persMatrix.Perspective(45.0f, (500 / (float)500), g_fzNear, g_fzFar);

    glUseProgram(g_FragWhiteDiffuseColor.theProgram);
    glUniformMatrix4fv(g_FragWhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
    glUniform2i(g_FragWhiteDiffuseColor.windowSizeUnif, 500, 500);

    glUseProgram(0);



    glUseProgram(g_FragWhiteDiffuseColortex.theProgram);
    glUniformMatrix4fv(g_FragWhiteDiffuseColortex.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
    glUniform2i(g_FragWhiteDiffuseColortex.windowSizeUnif, 500, 500);

    glUseProgram(0);





    if(g_pPlaneMesh && g_pCylinderMesh)
    {
        glutil::MatrixStack modelMatrix;
        modelMatrix.SetMatrix(g_viewPole.CalcMatrix());



        const glm::vec4 &worldLightPos = glm::vec4(xl, yl, zl, 1.0f);

        const glm::vec4 &lightPosCameraSpace = modelMatrix.Top() * worldLightPos;


        glUseProgram(g_FragWhiteDiffuseColor.theProgram);
        glUniform4f(g_FragWhiteDiffuseColor.lightIntensityUnif, 0.8f, 0.8f, 0.8f, 1.0f);
        glUniform4f(g_FragWhiteDiffuseColor.ambientIntensityUnif, 0.2f, 0.2f, 0.2f, 1.0f);
        glUniform3fv(g_FragWhiteDiffuseColor.cameraSpaceLightPosUnif,1, glm::value_ptr(lightPosCameraSpace));
        glUniform1f(g_FragWhiteDiffuseColor.lightAttenuationUnif, g_fLightAttenuation);
        glUniform1i(g_FragWhiteDiffuseColor.bUseRSquareUnif, g_bUseRSquare ? 1 : 0);
        glUniform1f(g_FragWhiteDiffuseColor.shininessFactorUnif, 0.2f);
        glUseProgram(0);



        glUseProgram(g_FragWhiteDiffuseColortex.theProgram);
        glUniform4f(g_FragWhiteDiffuseColortex.lightIntensityUnif, 0.8f, 0.8f, 0.8f, 1.0f);
        glUniform4f(g_FragWhiteDiffuseColortex.ambientIntensityUnif, 0.2f, 0.2f, 0.2f, 1.0f);
        glUniform3fv(g_FragWhiteDiffuseColortex.cameraSpaceLightPosUnif,1, glm::value_ptr(lightPosCameraSpace));
        glUniform1f(g_FragWhiteDiffuseColortex.lightAttenuationUnif, g_fLightAttenuation);
        glUniform1i(g_FragWhiteDiffuseColortex.bUseRSquareUnif, g_bUseRSquare ? 1 : 0);
        glUseProgram(0);




        {
            glutil::PushStack push(modelMatrix);

            //Render the ground plane.

            {
                glutil::PushStack push(modelMatrix);

                glm::mat3 normMatrix(modelMatrix.Top());
                normMatrix = glm::transpose(glm::inverse(normMatrix));

                glUseProgram(g_FragWhiteDiffuseColor.theProgram);
                glUniformMatrix4fv(g_FragWhiteDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE,
                    glm::value_ptr(modelMatrix.Top()));

                glUniformMatrix3fv(g_FragWhiteDiffuseColor.normalModelToCameraMatrixUnif, 1, GL_FALSE,
                    glm::value_ptr(normMatrix));
                glUniform4f(g_FragWhiteDiffuseColor.objectColorUnif, 0.2f, 0.84f, 0.2f, 1.0f);
                g_pPlaneMesh->Render();
                glUseProgram(0);
            }

            //light
            if(g_bDrawLight)
            {
                glutil::PushStack push(modelMatrix);

                //light time
                CalcLightPosition();

                modelMatrix.Translate(xl, yl, zl);
                modelMatrix.Scale(0.1f, 0.1f, 0.1f);

                glUseProgram(g_FragWhiteDiffuseColor.theProgram);
                glUniformMatrix4fv(g_FragWhiteDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE,
                    glm::value_ptr(modelMatrix.Top()));
                glUniform4f(g_FragWhiteDiffuseColor.objectColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
                g_pCubeMesh->Render("flat");
            }

            //cylinder
            {
                glutil::PushStack push(modelMatrix);

                modelMatrix.ApplyMatrix(g_objtPole.CalcMatrix());

                glm::mat3 normMatrix(modelMatrix.Top());
                normMatrix = glm::transpose(glm::inverse(normMatrix));
                modelMatrix.Translate(0.0f,0.0f,0.0f);
                    glUseProgram(g_FragWhiteDiffuseColortex.theProgram);

                    glActiveTexture(GL_TEXTURE0 + 5);
                    glBindSampler(1, g_samplers[0]);
                    glBindTexture(GL_TEXTURE_2D, g_textures[0]);
                    glUniform1i(g_FragWhiteDiffuseColortex.numberTextureUnif, 5);

                    glUniformMatrix4fv(g_FragWhiteDiffuseColortex.modelToCameraMatrixUnif, 1, GL_FALSE,
                        glm::value_ptr(modelMatrix.Top()));

                    glUniformMatrix3fv(g_FragWhiteDiffuseColortex.normalModelToCameraMatrixUnif, 1, GL_FALSE,
                        glm::value_ptr(normMatrix));
                    glUniform4f(g_FragWhiteDiffuseColortex.objectColorUnif, 0.452f, 0.623f, 0.592f, 1.0f);
                    g_pCylinderMesh->Render();

                glUseProgram(0);
            }


        }
    }

    glutPostRedisplay();
    glutSwapBuffers();
}

//Called whenever the window is resized. The new window size is given, in pixels.
//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
void reshape (int w, int h)
{
    glutil::MatrixStack persMatrix;
    persMatrix.Perspective(45.0f, (w / (float)h), g_fzNear, g_fzFar);

    glUseProgram(g_FragWhiteDiffuseColor.theProgram);
    glUniformMatrix4fv(g_FragWhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
    glUniform2i(g_FragWhiteDiffuseColor.windowSizeUnif, w, h);

    glUseProgram(0);

    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glutPostRedisplay();

}

0 个答案:

没有答案