著色器基礎(chǔ)應(yīng)用的兩個例子

1. 著色器ADS光照,Phong著色,紋理的使用,Disssovle丟棄片段的例子

1. 客戶端代碼
GLFrame             viewFrame;
GLFrustum           viewFrustum;
GLTriangleBatch     sphereBatch;
GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager     shaderManager;

GLuint    ADSLightShader;        
GLint    locAmbient;            
GLint   locDiffuse;            
GLint   locSpecular;       
GLint    locLight;            
GLint    locMVP;              
GLint    locMV;                
GLint    locNM;               
GLint    locTexture;
GLuint   locDissolve;
GLuint   texture;

bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) {
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    //讀取圖片像素
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    if(pBits == NULL)
    return false;
    //設(shè)置紋理環(huán)繞模式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    //設(shè)置紋理過濾模式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
    //像素以非包裝,每一個字節(jié)的方式進行存儲
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    //加載紋理
    glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
                 eFormat, GL_UNSIGNED_BYTE, pBits);
    //釋放像素
    free(pBits);

    if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
       minFilter == GL_LINEAR_MIPMAP_NEAREST ||
       minFilter == GL_NEAREST_MIPMAP_LINEAR ||
       minFilter == GL_NEAREST_MIPMAP_NEAREST)
    //預(yù)加載紋理Mip貼圖層,防止向前后移動幾何體時上面的貼圖加載過大,而出現(xiàn)性能消耗或者失真
    glGenerateMipmap(GL_TEXTURE_2D);

    return true;
}

void SetupRC(void){
    //設(shè)置背景顏色
    glClearColor(0.0, 0.0, 0.0, 1.0);
    //開啟深度測試
    glEnable(GL_DEPTH_TEST);
    //剔除看不見的面,提高性能
    glEnable(GL_CULL_FACE);
    //初始化存儲著色器
    shaderManager.InitializeStockShaders();
    //將角色幀向前移動
    viewFrame.MoveForward(4.0);
    //設(shè)置一個球體
    gltMakeSphere(sphereBatch, 1.0, 26, 13);
    //構(gòu)建一個著色器
    ADSLightShader = gltLoadShaderPairWithAttributes("ADSTexture.vp", "ADSTexture.fp", 3, GLT_ATTRIBUTE_VERTEX, "vVtertex", GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexture0");
    //定位統(tǒng)一值得到統(tǒng)一值管理對象
    locAmbient = glGetUniformLocation(ADSLightShader, "ambientColor");
    locDiffuse = glGetUniformLocation(ADSLightShader, "diffuseColor");
    locSpecular = glGetUniformLocation(ADSLightShader, "specularColor");
    locLight = glGetUniformLocation(ADSLightShader, "vLightPosition");
    locMVP = glGetUniformLocation(ADSLightShader, "mvpMatrix");
    locMV  = glGetUniformLocation(ADSLightShader, "mvMatrix");
    locNM  = glGetUniformLocation(ADSLightShader, "normalMatrix");
    locTexture = glGetUniformLocation(ADSLightShader, "colorMap");
    locDissolve = glGetUniformLocation(ADSLightShader, "dissolveFactor");
    //設(shè)置紋理對象
    glGenTextures(1, &texture);
    //綁定紋理
    glBindTexture(GL_TEXTURE_2D, texture);
    //載入并設(shè)置紋理
    LoadTGATexture("CoolTexture.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
}

void ShutdownRC(void){
    //刪除紋理對象
    glDeleteTextures(1, &texture);
}

void RenderScene(void){
    
    static CStopWatch rotTimer;

    //清除顏色緩沖區(qū)和深度緩沖區(qū)數(shù)據(jù)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //將角色幀對應(yīng)的幾何體和頂部的模型視圖堆棧矩陣相乘放入模型視圖堆棧的頂部
    modelViewMatrix.PushMatrix(viewFrame);
    //將堆棧中的角色幀旋轉(zhuǎn)
    modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f);
    //設(shè)置光線位置
    GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };
    //設(shè)置環(huán)境光顏色
    GLfloat vAmbientColor[] = { 0.2f, 0.2f, 0.2f, 1.0f };
    //設(shè)置漫射光顏色
    GLfloat vDiffuseColor[] = { 1.0f, 1.0f, 1.0f, 1.0f};
    //設(shè)置反射光顏色
    GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    //使用著色器程序
    glUseProgram(ADSLightShader);
    //設(shè)置環(huán)境光初始值
    glUniform4fv(locAmbient, 1, vAmbientColor);
    //設(shè)置漫射光初始值
    glUniform4fv(locDiffuse, 1, vDiffuseColor);
    //設(shè)置折射光初始值
    glUniform4fv(locSpecular, 1, vSpecularColor);
    //設(shè)置光源位置
    glUniform3fv(locLight, 1, vEyeLight);
    //設(shè)置模型視圖投影矩陣
    glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
    //設(shè)置模型視圖矩陣
    glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());
    //設(shè)置世界坐標系的幾何表面法向矩陣
    glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());
    //得到綁定的紋理對象
    glBindTexture(GL_TEXTURE_2D, texture);
    //設(shè)置紋理使用的Mip紋理貼圖為基層
    glUniform1i(locTexture, 0);
    float fFactor = fmod(rotTimer.GetElapsedSeconds(), 20.0f);
    fFactor /= 20.0f;
    glUniform1f(locDissolve, fFactor);
    // 繪制
    sphereBatch.Draw();
    // 角色幀出棧
    modelViewMatrix.PopMatrix();
    //雙緩沖區(qū)交換數(shù)據(jù)
    glutSwapBuffers();
    //窗口刷新顯示
    glutPostRedisplay();
}

void ChangeSize(int w, int h){
    if (h == 0){
        h = 1;
    }
    //設(shè)置視口大小
    glViewport(0, 0, w, h);
    //設(shè)置投影錐體
    viewFrustum.SetPerspective(35.0, float(w)/float(h), 1.0, 100.0);
    //載入投影矩陣到投影堆棧
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    //設(shè)置管線管理模型視圖矩陣堆棧和投影矩陣堆棧
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Lit Texture");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    SetupRC();
    glutMainLoop();
    ShutdownRC();
    return 0;
}
2. 著色器代碼
//頂點著色器
//設(shè)置著色器版本
#version 120
//頂點著色器屬性
attribute vec4 vVertex;
attribute vec3 vNormal;
attribute vec4 vTexture0;
//統(tǒng)一值
uniform mat4   mvpMatrix;
uniform mat4   mvMatrix;
uniform mat3   normalMatrix;
uniform vec3   vLightPosition;
//下一階段輸出值
varying vec3 vVaryingNormal;
varying vec3 vVaryingLightDir;
varying vec2 vTexCoords;

void main(void) {
    //得到視覺坐標系下的法向量
    vVaryingNormal = normalMatrix * vNormal;
    //得到視覺坐標系下的頂點
    vec4 vPosition4 = mvMatrix * vVertex;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
    //得到單位光源向量
    vVaryingLightDir = normalize(vLightPosition - vPosition3);
    //設(shè)置紋理坐標,紋理坐標會映射紋理單元的地址
    vTexCoords = vTexture0.st;
    // 對頂點進行模型視圖投影變換計算
    gl_Position = mvpMatrix * vVertex;
}
//片段著色器
//設(shè)置著色器版本號
#version 120
//統(tǒng)一值
uniform vec4      ambientColor;
uniform vec4      diffuseColor;   
uniform vec4      specularColor;
uniform sampler2D colorMap;
uniform float     dissolveFactor;
//上一階段輸入值
varying vec3 vVaryingNormal;
varying vec3 vVaryingLightDir;
varying vec2 vTexCoords;
//這里用到了Phong著色,只是向片段著色器傳入沒有插值顏色的頂點,因為插值顏色頂點是分布不均的,這樣可能會出現(xiàn)光照不均的不想要的結(jié)果
//這里將顏色值作為統(tǒng)一值直接傳給了片段著色器處理,代價是更多的性能消耗
void main(void) {
    //通過紋理坐標找到需要貼圖的幾何體對應(yīng)的紋理單元的紋理顏色值
    vec4 vCloudSample = texture2D(colorMap, vTexCoords);
    //當(dāng)紋理單元的r值小于dissolveFactor時,舍棄該片段
    if(vCloudSample.r < dissolveFactor)
      discard;
    // 得到法向量和光源向量的夾角,夾角的強度模擬漫射光在不同光源位置下的強度
    float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
    // 得到漫射光
    gl_FragColor = diff * diffuseColor;
    // 添加環(huán)境光
    gl_FragColor += ambientColor;
    // 這里先照亮紋理,因為紋理值乘以純白色只會得到一個照亮的紋理值,不會表現(xiàn)出高光,然后在進行高光折射光的處理
    //通過紋理坐標找到需要貼圖的幾何體對應(yīng)的紋理單元的紋理顏色值通過相乘添加到之前的光源上得到新的光柵顏色值
    gl_FragColor *= texture2D(colorMap, vTexCoords);
    // 得到折射向量
    vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
    // 得到反射光與法向量的夾角
    float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
    if(diff != 0) {
        //得到漫射光強度,其實OpenGL的照相機隱藏的做了視線的管理,反射光的強度是視覺向量和反射光向量的夾角值
        float fSpec = pow(spec, 128.0);
        //添加反射光
        gl_FragColor.rgb += vec3(fSpec, fSpec, fSpec);
    }
}

2. 紋理模擬光源

1. 客戶端代碼
GLFrame             viewFrame;
GLFrustum           viewFrustum;
GLTriangleBatch     torusBatch;
GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager     shaderManager;

GLuint  toonShader;
GLint   locLight;
GLint   locMVP;
GLint   locMV;
GLint   locNM;
GLint   locColorTable;
GLuint  texture;

void SetupRC(void) {
    //設(shè)置背景顏色
    glClearColor(0.025f, 0.25f, 0.25f, 1.0f );
    //開啟深度測試,防止圖元重疊
    glEnable(GL_DEPTH_TEST);
    //開啟圖元剔除,剔除看不見的圖元提高性能
    glEnable(GL_CULL_FACE);
    //初始化存儲著色器
    shaderManager.InitializeStockShaders();
    //角色幀向前移動
    viewFrame.MoveForward(4.0f);
    //設(shè)置花托,通過torusBatch容器管理
    gltMakeTorus(torusBatch, 0.80f, 0.25f, 52, 26);
    //生成著色器程序
    toonShader = gltLoadShaderPairWithAttributes("ToonShader.vp", "ToonShader.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex",
                                                 GLT_ATTRIBUTE_NORMAL, "vNormal");
    //定位統(tǒng)一值,得到統(tǒng)一值管理對象
    locLight = glGetUniformLocation(toonShader, "vLightPosition");
    locMVP = glGetUniformLocation(toonShader, "mvpMatrix");
    locMV  = glGetUniformLocation(toonShader, "mvMatrix");
    locNM  = glGetUniformLocation(toonShader, "normalMatrix");
    locColorTable = glGetUniformLocation(toonShader, "colorTable");
    //設(shè)置紋理對象
    glGenTextures(1, &texture);
    //綁定紋理
    glBindTexture(GL_TEXTURE_1D, texture);
    //設(shè)置一維紋理對應(yīng)的像素數(shù)據(jù)(RGB),一維紋理的坐標大于0小于1,通過一維紋理坐標會映射到紋理地址,著色器會通過法向量和光源向量夾角來表示一維紋理坐標來模擬漫射光強度,
    GLubyte textureData[4][3] = { 32,  0, 0,
        64,  0, 0,
        128, 0, 0,
        255, 0, 0};
    //載入紋理,一維紋理,當(dāng)前層為基層,壓縮方式為rgb,長度是4,邊框為0,紋理數(shù)據(jù)為無符號,像素是textureData
    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
    //設(shè)置紋理過濾方式
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    //設(shè)置紋理環(huán)繞模式
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    //預(yù)加載紋理Mip貼圖層,防止向前后移動幾何體時上面的貼圖加載過大,而出現(xiàn)性能消耗或者失真
    glGenerateMipmap(GL_TEXTURE_1D);
}

void ShutdownRC(void) {
    //清理紋理對象
    glDeleteTextures(1, &texture);
}

// Called to draw scene
void RenderScene(void) {
    static CStopWatch rotTimer;
    //清除顏色緩沖區(qū)數(shù)據(jù),清除深度緩沖區(qū)數(shù)據(jù)和
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //將角色幀對應(yīng)的幾何體的頂點和頂部的模型視圖矩陣堆棧矩陣相乘放入模型視圖矩陣堆棧的頂部
    modelViewMatrix.PushMatrix(viewFrame);
    //模型視圖變換,旋轉(zhuǎn)變換
    modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f);
    //設(shè)置光線位置
    GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };
    //使用著色器程序
    glUseProgram(toonShader);
    //設(shè)置著色器統(tǒng)一值
    glUniform3fv(locLight, 1, vEyeLight);
    glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
    glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());
    glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());
    glUniform1i(locColorTable, 0);
    //繪制
    torusBatch.Draw();
    //移出模型視圖堆棧底部的矩陣
    modelViewMatrix.PopMatrix();
    //交換前后臺緩沖區(qū)數(shù)據(jù)
    glutSwapBuffers();
    //刷新展示
    glutPostRedisplay();
}


void ChangeSize(int w, int h) {
    if(h == 0){
       h = 1;
    }
    //設(shè)置視口
    glViewport(0, 0, w, h);
    //設(shè)置投影變換
    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
    //載入投影矩陣到投影矩陣堆棧
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    //設(shè)置管線管理模型視圖矩陣堆棧和投影矩陣堆棧
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

int main(int argc, char* argv[]) {
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Cell (toon) shading");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    SetupRC();
    glutMainLoop();
    ShutdownRC();
    return 0;
}
2. 著色器代碼
//頂點著色器
//設(shè)置著色器版本
#version 120
//設(shè)置頂點著色器屬性
attribute vec4 vVertex;
attribute vec3 vNormal;
//下一階段輸出值
varying float textureCoordinate;
//統(tǒng)一值
uniform vec3    vLightPosition;
uniform mat4    mvpMatrix;
uniform mat4    mvMatrix;
uniform mat3    normalMatrix;
void main(void) {
    //設(shè)置視覺坐標系下的單位法向量
    vec3 vEyeNormal = normalMatrix * vNormal;
    //設(shè)置視覺坐標系下的頂點值
    vec4 vPosition4 = mvMatrix * vVertex;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
    //設(shè)置光源向量
    vec3 vLightDir = normalize(vLightPosition - vPosition3);
    //得到法向量與光線向量的夾角,這個值作為片段著色器一維紋理的尋址坐標
    //一維紋理單元坐標是大于0小于1的會映射到一維紋理單元的地址,正好可用夾角值模擬
    textureCoordinate = max(0.0, dot(vEyeNormal, vLightDir));
    //對頂點進行模型視圖投影矩陣變換計算
    gl_Position = mvpMatrix * vVertex;
}
//片段著色器
//著色器版本
#version 120
//統(tǒng)一值
uniform sampler1D colorTable;
//上一階段輸出值
varying float textureCoordinate;
void main(void) {
   //通過紋理坐標找到紋理單元得到紋理顏色值
   //對紋理顏色光柵化
   gl_FragColor = texture1D(colorTable, textureCoordinate);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 紋理基礎(chǔ) 紋理是一種結(jié)構(gòu)化的存儲形式(Textures are a structured form of st...
    RichardJieChen閱讀 16,593評論 0 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,644評論 19 139
  • 1 前言 一直想沿著圖像處理這條線建立一套完整的理論知識體系,同時積累實際應(yīng)用經(jīng)驗。因此有了從使用AVFounda...
    RichardJieChen閱讀 5,934評論 5 12
  • 油鹽醬醋柴米茶 全部倒入在鍋中 水到渠成飯煮熟 一桌飯菜樂哈哈 ---寫于2006年。
    卡布奇諾花蜜閱讀 564評論 0 49
  • 我的家很小,卻總是滿當(dāng)當(dāng)?shù)摹年柵_的一圈原木色矮柜延伸到一體的書桌、床頭、上個世紀貼壁的衣柜邊角,走出臥室爬到客廳...
    nirvanafish閱讀 229評論 0 1

友情鏈接更多精彩內(nèi)容