2012-05-15 5 views
1

Я пишу программу для реализации сопоставления среды с использованием языка OpenGL и Cg shader. Но результат не очень правильный. При вычислении цвета модели мы будем смешивать отражение с текстурой деколя. Единый параметр, называемый отражательной способностью , позволяет приложению контролировать, насколько отражающим является материал.сопоставление окружения с использованием OpenGL и Cg

Во-первых, я перечисляю мой фрагмент Cg код:

void main_f(float2 texCoord : TEXCOORD0, 
    float3 R : TEXCOORD1, 

    out float4 color : COLOR, 

    uniform float reflectivity, 
    uniform sampler2D decalMap, 
    uniform samplerCUBE environmentMap) 
{ 
//fetch reflected environment color 
float3 reflectedColor = texCUBE(environmentMap,R); 

//fetch the decal base coloe 
float3 decalColor = tex2D(decalMap,texCoord); 
color.xyz = lerp(reflectedColor,decalColor,reflectivity);//change !!!!!!!! 
color.w = 1; 
} 

Я установил единообразного параметр отражательной, как 0.6.And результат: enter image description here

Как мы можем видеть, информацию о цвете от Текстура декалирования теряется. Есть только информация о цвете от текстуры куба среды. И если я задаю коэффициент отражения как 0, модель будет темной. Но если изменить color.xyz в коде Cg фрагмент как:

color.xyz = decalColor; 

я могу получить правильный результат (только имеет цвет от деколи текстуры): enter image description here

И если я изменить цвет .xyz в фрагменте кода Cg как:

color.xyz = reflectedColor; 

я могу получить правильный результат (только имеет цвет от среды кубической текстуры), также: enter image description here

И мой вопрос: Почему это не работает, когда я смешиваю информацию о цвете от текстуры деколя с информацией о цвете от текстуры куба среды с помощью функции Cg lerp?

наконец я перечисляю мой CG вершинного шейдера и CPP файл: vertex.cg:

void main_v(float4 position : POSITION, 
       float2 texCoord : TEXCOORD0,//decal texture 
       float3 normal : NORMAL, 

       out float4 oPosition : POSITION, 
       out float2 oTexCoord : TEXCOORD0,//out decal texture 
       out float3 R : TEXCOORD1,//reflective vector 

       uniform float3 eyePositionW,//eye position in world space 
       uniform float4x4 modelViewProj, 
       uniform float4x4 modelToWorld 
       ) 
{ 
     modelViewProj = glstate.matrix.mvp; 
     oPosition = mul(modelViewProj,position);   
     oTexCoord = texCoord; 

     float3 positionW = mul(modelToWorld,position).xyz; 
     float3 N = mul((float3x3)modelToWorld,normal); 
     N = normalize(N); 

     float3 I = positionW - eyePositionW;//incident vector 
     R = reflect(I,N); 
} 

main.cpp:

#pragma comment(lib,"glew32.lib") 
#pragma comment(lib,"GLAUX.LIB") 
#pragma comment(lib,"cg.lib") 
#pragma comment(lib,"cgGL.lib") 

#include <GL/glew.h> 
#include <GL/glut.h> 
#include <GL/glaux.h> 
#include <CG/cg.h> 
#include <CG/cgGL.h> 
#include "MonkeyHead.h" 
#include <iostream> 
#include <cmath> 

using namespace std; 

int loop; 
/* Use enum to assign unique symbolic OpenGL texture names. */ 
enum { 
    TO_BOGUS = 0, 
    TO_DECAL, 
    TO_ENVIRONMENT, 
}; 
const double myPi = 3.14159; 
//for Cg shader 
static CGcontext myCgContext; 
static CGprofile myCgVertexProfile,myCgFragmentProfile; 
static CGprogram myCgVertexProgram,myCgFragmentProgram; 
static const char *myProgramName = "CgTest18CubeMapReflective", 
         *myVertexProgramFileName = "vertex.cg", 
         *myVertexProgramName = "main_v", 
         *myFragmentProgramFileName = "fragment.cg", 
         *myFragmentProgramName = "main_f"; 
static CGparameter myCgVertexParam_modelToWorld; 

//bmp files for cube map 
const char *bmpFile[6] = {"Data/1.bmp","Data/2.bmp","Data/3.bmp", 
             "Data/4.bmp","Data/5.bmp","Data/6.bmp"}; 
const char *decalBmpFile = "Data/decal.bmp"; 
static float eyeAngle = 0.53; 
static float eyeHeight = 0.0f; 
static float headSpain = 0.0f; 
static const GLfloat vertex[4*6][3] = { 
    /* Positive X face. */ 
    { 1, -1, -1 }, { 1, 1, -1 }, { 1, 1, 1 }, { 1, -1, 1 }, 
    /* Negative X face. */ 
    { -1, -1, -1 }, { -1, 1, -1 }, { -1, 1, 1 }, { -1, -1, 1 }, 
    /* Positive Y face. */ 
    { -1, 1, -1 }, { 1, 1, -1 }, { 1, 1, 1 }, { -1, 1, 1 }, 
    /* Negative Y face. */ 
    { -1, -1, -1 }, { 1, -1, -1 }, { 1, -1, 1 }, { -1, -1, 1 }, 
    /* Positive Z face. */ 
    { -1, -1, 1 }, { 1, -1, 1 }, { 1, 1, 1 }, { -1, 1, 1 }, 
    /* Negative Z face. */ 
    { -1, -1, -1 }, { 1, -1, -1 }, { 1, 1, -1 }, { -1, 1, -1 }, 
}; 
static float reflectivity = 0.6; 
GLuint decalTexture; 
bool animating = false;//enable animating or not 

static void drawMonkeyHead() 
{ 
    static GLfloat *texCoords = NULL; 
    const int numVertices = sizeof(MonkeyHead_vertices) 
     /(3 * sizeof(MonkeyHead_vertices[0])); 
    const float scaleFactor = 1.5; 
    //generate texcoords 
    texCoords = (GLfloat*)malloc(2 * numVertices * sizeof(GLfloat)); 
    if (!texCoords) 
    { 
     cerr << "ERROR : Monkey head texcoords memory malloc failed !" << endl; 
     exit(1); 
    } 
    for (loop = 0;loop < numVertices;++loop) 
    { 
     texCoords[loop * 2] = scaleFactor * MonkeyHead_vertices[3 * loop]; 
     texCoords[loop * 2 + 1] = scaleFactor * MonkeyHead_vertices[3 * loop + 1]; 
    } 

    //use vertex array 
    //enable array 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_NORMAL_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
    //assign array data 
    glVertexPointer(3,GL_FLOAT,3 * sizeof(GLfloat),MonkeyHead_vertices); 
    glNormalPointer(GL_FLOAT,3 * sizeof(GLfloat),MonkeyHead_normals); 
    glTexCoordPointer(2,GL_FLOAT,2 * sizeof(GLfloat),texCoords); 

    glDrawElements(GL_TRIANGLES,3 * MonkeyHead_num_of_triangles, 
     GL_UNSIGNED_SHORT,MonkeyHead_triangles); 
} 


//read bmp image file 
AUX_RGBImageRec *LoadBMP(const char *FileName) 
{ 
    FILE *File = NULL; 
    if(!FileName) 
     return NULL; 
    File = fopen(FileName,"r"); 
    if (File) 
    { 
     fclose(File); 
     return auxDIBImageLoad(FileName); 
    } 
    return NULL; 
} 

//load decal texture from a bmp file 
int loadDecalTexture() 
{ 
    int status = 1; 
    AUX_RGBImageRec *TextureImage = NULL; 
    if ((TextureImage = LoadBMP(decalBmpFile))) 
    { 
     glGenTextures(1,&decalTexture); 
     glBindTexture(GL_TEXTURE_2D,decalTexture); 
     glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TextureImage->sizeX, 
      TextureImage->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE, 
      TextureImage->data);//指定纹理 
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//指定过滤模式 
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
    } 
    else 
     status = 0; 
    if (TextureImage) 
    { 
     if (TextureImage->data) 
      free(TextureImage->data); 
     free(TextureImage); 
    } 

    return status; 
} 

//load cube map from 6 bmp files 
int loadCubeMap() 
{ 
    int status = 1; 
    AUX_RGBImageRec *TextureImage[6] = {NULL,NULL,NULL,NULL,NULL,NULL}; 
    for (loop = 0;loop < 6;++loop) 
    { 
     if (!(TextureImage[loop] = LoadBMP(bmpFile[loop]))) 
     { 
      cout << "ERROR :load bmp file " << loop << " failed !" << endl; 
      status = 0; 
     } 
    } 

    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, TextureImage[0] ->sizeX, TextureImage[0] ->sizeY, 
     0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0] ->data); 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, TextureImage[1] ->sizeX, TextureImage[1] ->sizeY, 
     0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[1] ->data); 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, TextureImage[2] ->sizeX, TextureImage[2] ->sizeY, 
     0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[2] ->data); 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, TextureImage[3] ->sizeX, TextureImage[3] ->sizeY, 
     0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[3] ->data); 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, TextureImage[4] ->sizeX, TextureImage[4] ->sizeY, 
     0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[4] ->data); 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, TextureImage[5] ->sizeX, TextureImage[5] ->sizeY, 
     0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[5] ->data); 

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    //free memory 
    for (loop = 0;loop < 6;++loop) 
    { 
     if (TextureImage[loop]) 
     { 
      if (TextureImage[loop] ->data) 
      { 
       free(TextureImage[loop] ->data); 
      } 
      free(TextureImage[loop]); 
     } 
    } 

    return status; 
} 

//draw th surroundings as a cube with each face of 
//the cube environment map applied. 
void drawSurroundings(const GLfloat *eyePosition) 
{ 
    const float surroundingsDistance = 8; 

    glLoadIdentity(); 
    gluLookAt(eyePosition[0],eyePosition[1],eyePosition[2], 
     0,0,0,0,1,0); 
    glScalef(surroundingsDistance, 
     surroundingsDistance, 
     surroundingsDistance); 

    glEnable(GL_TEXTURE_CUBE_MAP); 
    glBindTexture(GL_TEXTURE_CUBE_MAP,TO_ENVIRONMENT); 
    glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); 

    glBegin(GL_QUADS); 
     for (loop = 0;loop < 4 * 6;++loop) 
     { 
      glTexCoord3fv(vertex[loop]); 
      glVertex3fv(vertex[loop]); 
     } 
    glEnd(); 
} 

static void checkForCgError(const char *situation) 
{ 
    CGerror error; 
    const char *string = cgGetLastErrorString(&error); 

    if (error != CG_NO_ERROR) { 
     cout << "ERROR : " << myProgramName << situation << string << endl; 
     if (error == CG_COMPILER_ERROR) { 
      cout << cgGetLastListing(myCgContext) << endl; 
     } 
     exit(1); 
    } 
} 

//init Cg shaders 
void initCg() 
{ 
    myCgContext = cgCreateContext(); 

    myCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); 
    cgGLSetOptimalOptions(myCgVertexProfile); 
    checkForCgError("selecting vertex profile"); 

    myCgVertexProgram = cgCreateProgramFromFile(
     myCgContext, 
     CG_SOURCE, 
     myVertexProgramFileName, 
     myCgVertexProfile, 
     myVertexProgramName, 
     NULL); 
    checkForCgError("Creating vertex Cg program from file"); 

    cgGLLoadProgram(myCgVertexProgram); 
    checkForCgError("loading vertex program"); 

    myCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); 
    cgGLSetOptimalOptions(myCgFragmentProfile); 
    checkForCgError("selecting fragment profile"); 

    myCgFragmentProgram = cgCreateProgramFromFile(
     myCgContext, 
     CG_SOURCE, 
     myFragmentProgramFileName, 
     myCgFragmentProfile, 
     myFragmentProgramName, 
     NULL); 
    checkForCgError("Creating fragment Cg program from file"); 

    cgGLLoadProgram(myCgFragmentProgram); 
    checkForCgError("loading fragment program"); 
} 

//compute rotate transformation matrix 
void makeRotateMatrix(float angle, 
         float ax,float ay,float az, 
         float m[16]) 
{ 
    float radians, sine, cosine, ab, bc, ca, tx, ty, tz; 
    float axis[3]; 
    float mag; 

    axis[0] = ax; 
    axis[1] = ay; 
    axis[2] = az; 
    mag = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); 
    if (mag) { 
     axis[0] /= mag; 
     axis[1] /= mag; 
     axis[2] /= mag; 
    } 

    radians = angle * myPi/180.0; 
    sine = sin(radians); 
    cosine = cos(radians); 
    ab = axis[0] * axis[1] * (1 - cosine); 
    bc = axis[1] * axis[2] * (1 - cosine); 
    ca = axis[2] * axis[0] * (1 - cosine); 
    tx = axis[0] * axis[0]; 
    ty = axis[1] * axis[1]; 
    tz = axis[2] * axis[2]; 

    m[0] = tx + cosine * (1 - tx); 
    m[1] = ab + axis[2] * sine; 
    m[2] = ca - axis[1] * sine; 
    m[3] = 0.0f; 
    m[4] = ab - axis[2] * sine; 
    m[5] = ty + cosine * (1 - ty); 
    m[6] = bc + axis[0] * sine; 
    m[7] = 0.0f; 
    m[8] = ca + axis[1] * sine; 
    m[9] = bc - axis[0] * sine; 
    m[10] = tz + cosine * (1 - tz); 
    m[11] = 0; 
    m[12] = 0; 
    m[13] = 0; 
    m[14] = 0; 
    m[15] = 1; 
} 

//compute translation transformation matrix 
static void makeTranslateMatrix(float x, float y, float z, float m[16]) 
{ 
    m[0] = 1; m[1] = 0; m[2] = 0; m[3] = x; 
    m[4] = 0; m[5] = 1; m[6] = 0; m[7] = y; 
    m[8] = 0; m[9] = 0; m[10] = 1; m[11] = z; 
    m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; 
} 

//multiply a floar4x4 matrix by another float4x4 matrix 
static void multMatrix(float dst[16],const float src1[16],const float src2[16]) 
{ 
    for (int i = 0;i < 4;++i) 
    { 
     for (int j = 0;j < 4;++j) 
     { 
      dst[i * 4 + j] = src1[i * 4 + 0] * src2[0 * 4 + j] + 
            src1[i * 4 + 1] * src2[1 * 4 + j] + 
            src1[i * 4 + 2] * src2[2 * 4 + j] + 
            src1[i * 4 + 3] * src2[3 * 4 + j]; 
     } 
    } 
} 

void init() 
{ 
    glewInit(); 
    glClearColor(0.0,0.0,0.0,1.0); 
    glShadeModel(GL_SMOOTH); 
    glEnable(GL_DEPTH_TEST); 

    if (!loadDecalTexture()) 
    { 
     cout << "ERROR : load decal texture from bmp file failed !" << endl; 
     exit(1); 
    } 

    glBindTexture(GL_TEXTURE_CUBE_MAP,TO_ENVIRONMENT); 
    if (!loadCubeMap()) 
    { 
     cout << "ERROR : load cube map from bmp file failed !" << endl; 
     exit(1); 
    } 


    initCg(); 
} 

void display() 
{ 
    const GLfloat eyePosition[4] = {6 * sin(eyeAngle), 
               eyeHeight, 
               6 * cos(eyeAngle), 
               1}; 
    float tranlateMatrix[16],rotateMatrix[16],modelMatrix[16]; 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    cgGLEnableProfile(myCgVertexProfile); 
    checkForCgError("enabling vertex profile"); 

    cgGLEnableProfile(myCgFragmentProfile); 
    checkForCgError("enabling fragment profile"); 

    cgGLBindProgram(myCgVertexProgram); 
    checkForCgError("binding vertex program"); 

    cgGLBindProgram(myCgFragmentProgram); 
    checkForCgError("binding fragment program"); 

    glLoadIdentity(); 
    glTranslatef(0.0,0.0,-5.0); 
    glRotatef(headSpain,0,1,0); 

    //set some uniform parameters in Cg shader 
    cgGLSetParameter3fv(
     cgGetNamedParameter(myCgVertexProgram,"eyePositionW"), 
     eyePosition); 
    checkForCgError("setting eyePositionW parameter"); 

    makeRotateMatrix(headSpain,0,1,0,rotateMatrix); 
    makeTranslateMatrix(0.0,0.0,-5.0,tranlateMatrix); 
    multMatrix(modelMatrix,tranlateMatrix,rotateMatrix); 
    //set the Cg matrix parameter : modelToWorld 
    cgSetMatrixParameterfr(
     cgGetNamedParameter(myCgVertexProgram,"modelToWorld"), 
     modelMatrix); 
    checkForCgError("setting modelToWorld parameter"); 
    cgGLSetParameter1f(
     cgGetNamedParameter(myCgFragmentProgram,"reflectivity"), 
     reflectivity); 
    checkForCgError("setting reflectivity parameter"); 

    cgGLSetTextureParameter(
     cgGetNamedParameter(myCgFragmentProgram,"decalMap"), 
     decalTexture); 
    checkForCgError("setting decalTexture parameter"); 
    cgGLSetTextureParameter(
     cgGetNamedParameter(myCgFragmentProgram,"environmentMap"), 
     TO_ENVIRONMENT); 
    checkForCgError("setting environmentMap parameter"); 

    drawMonkeyHead(); 

    cgGLDisableProfile(myCgVertexProfile); 
    checkForCgError("disabling vertex profile"); 

    cgGLDisableProfile(myCgFragmentProfile); 
    checkForCgError("disabling fragment profile"); 


    drawSurroundings(eyePosition); 

    glutSwapBuffers(); 
} 

static void idle() 
{ 
    headSpain += 0.5; 
    if (headSpain > 360) 
    { 
     headSpain -= 360; 
    } 
    glutPostRedisplay(); 
} 

static void keyboard(unsigned char key,int x,int y) 
{ 
    switch(key) 
    { 
    case ' ': 
     animating = !animating; 
     if (animating) 
     { 
      glutIdleFunc(idle); 
     } 
     else 
      glutIdleFunc(NULL); 
     break; 
    case 'r': 
     reflectivity += 0.1; 
     if (reflectivity > 1.0) 
     { 
      reflectivity = 1.0; 
     } 
     cout << "reflectivity : " << reflectivity << endl; 
     glutPostRedisplay(); 
     break; 
    case 'R': 
     reflectivity -= 0.1; 
     if (reflectivity < 0.0) 
     { 
      reflectivity = 0.0; 
     } 
     cout << "reflectivity : " << reflectivity << endl; 
     glutPostRedisplay(); 
     break; 
    case 27: 
     cgDestroyProgram(myCgVertexProgram); 
     cgDestroyContext(myCgContext); 
     exit(0); 
     break; 
    } 
} 

void reshape(int w,int h) 
{ 
    glViewport(0,0,(GLsizei)w,(GLsizei)h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(60.0,1,1.0,20.0); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 

int main(int argc,char** argv) 
{ 
    glutInit(&argc,argv); 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowPosition(0,0); 
    glutInitWindowSize(600,600); 
    glutCreateWindow("CubeMapReflection"); 
    init(); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutKeyboardFunc(keyboard); 

    glutMainLoop(); 

    return 0; 
} 

ответ

0

Первое, что я вижу, что потребности лерп заявление чтобы его значения изменились.

color.xyz = lerp(reflectedColor,decalColor,reflectivity);//change !!!!!!!! 

должен быть

color.xyz = lerp(decalColor, reflectedColor, reflectivity); 

потому что lerp documentation говорит:

лерп (а, б, ж) возвращает при ш = 0 и Ь при ш = 1, и вы хотите полный этикету когда отражательная способность = 0 и полная отражается, когда коэффициент отражения = 1.

Я вижу, что эффект, который вы пытаетесь достичь, сродни GL_MODULATE. Вам понадобится несколько значений вместе, а не lerp между ними. Попробуйте это, он должен работать и дать вам эффект, который вы хотите.

color.xyz = (reflectedColor.xyz * reflectivity) * decalColor; 
+0

Извините, но это не работает, хотя то, что вы сказали о функции lerp, является правильным. В моей программе я установил коэффициент отражения как 0.6, Даже я неправильно использую функцию lerp, информация о цвете от текстуры деколя не должна быть потеряна ~~~ Мне очень любопытно ~~~ – XiaJun

+0

Ну, я не уверен, что простое умножение - такая хорошая идея, так как этот путь небольшая отражательная способность просто уменьшает весь цвет, даже цвет деколя. Думаю, его подход взвешенной суммы - не такая уж плохая идея. –

+0

Правда, теперь я не уверен в регулировании отражательной способности, но я уверен, что умножение - это то, что GL_MODULATE делает и должно давать правильные результаты. – Ani

 Смежные вопросы

  • Нет связанных вопросов^_^