成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

OpenGL進階(十二)-基礎(chǔ)著色(Shading)-創(chuàng)新互聯(lián)

提要

經(jīng)過前面的關(guān)于GLSL基礎(chǔ)學(xué)習(xí),可以參考OpenGL進階專欄中的一些文章。

大柴旦網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)建站于2013年開始到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)建站

接下來的內(nèi)容將會非常的有意思,比如全局光照,環(huán)境貼圖,法線貼圖,景深....是不是聽著就很棒!想要學(xué)習(xí)的話,當(dāng)然需要付出更多的努力!不過一切都是值得的。

今天的內(nèi)容主要是關(guān)于光照的一些基礎(chǔ)著色。

    在光照模型中,光照主要由三部分組成:環(huán)境光(ambient),漫反射(diffuse),鏡面反射(specular)。環(huán)境光是那些在環(huán)境中進行充分的散射,無法分辨方向的光,它似乎時來自所有方向的。漫反射來自某個方向,因此,如果它從正面照射表面,它看起來顯得更亮一些,反之,如果它是斜著掠過表面,它看起來就顯得暗一些,當(dāng)它撞擊到物體的表面的時候,它會均勻地向所有的方向發(fā)散。鏡面光來自一個特定的方向,并且傾向于從表面某個特定的方向反射,當(dāng)有一束激光從一面鏡子上反彈回來時,它所產(chǎn)生的幾乎是百分百的鏡面反射光。

關(guān)于光照的原理及編程實現(xiàn),可以參考另一篇文章:光線追蹤(RayTracing)算法理論與實踐(三)光照


單點光照下的漫反射著色

這里需要用到一個模型,來自stanford的兔子 - bunny,在文章的最后有下載,最好自己加載到blender里面再導(dǎo)出一遍,不然似乎沒有法線信息。

程序?qū)崿F(xiàn)的思路:

1)加載obj模型。

2)將頂點法線坐標(biāo)存到VBO中,并作為參數(shù)傳到shader中去。

3)在shader中定義關(guān)于光照以及MVP的Uniform變量。

4)在程序中設(shè)置uniform變量。

5)在定點shader中計算頂點位置和光照強度,在片段shader中對片段進行著色。

具體的代碼實現(xiàn)如下。

首先在代碼中添加一個ObjObject類,用來表示Obj模型類。

objobject.h

#ifndef OBJOBJECT_H #define OBJOBJECT_H #include "util.h"  class ObjObject {     public:         ObjObject();         ObjObject(const char * path);         virtual ~ObjObject();         int getVerticesCount();         vector<glm::vec3> vertices;         vector<glm::vec2> uvs;         vector<glm::vec3> normals;     protected:     private:  };  #endif // TEAPOT_H

objobject.cpp

#include "objobject.h"  ObjObject::ObjObject() {     //ctor }  ObjObject::~ObjObject() {     //dtor }  ObjObject::ObjObject(const char * path) {     Util u;     u.loadOBJ(path, this->vertices, this->uvs, this->normals); }  int ObjObject::getVerticesCount() {     return this->vertices.size(); }

接著就是在渲染中一步步實現(xiàn)上面提到的步驟了。

在initGL中對bunny進行初始化:

 bunny = ObjObject("bunny.obj");

然后生成定點和法線相對應(yīng)的 VAO,VBO,同時加載shader

void CGL::compileShader() {  	glGenVertexArrays(1, &VertexArrayID); 	glBindVertexArray(VertexArrayID);  	glGenBuffers(1, &vertexbuffer); 	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); 	glBufferData(GL_ARRAY_BUFFER, bunny.vertices.size() * sizeof(glm::vec3), &bunny.vertices[0], GL_STATIC_DRAW); //glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), positionData, GL_STATIC_DRAW);  // 1rst attribute buffer : vertices 		glEnableVertexAttribArray(0); 		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); 		glVertexAttribPointer( 			0,                  // attribute 			3,                  // size 			GL_FLOAT,           // type 			GL_FALSE,           // normalized? 			0,                  // stride 			(void*)0            // array buffer offset 		);      GLuint normalbuffer; 	glGenBuffers(1, &normalbuffer); 	glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); 	glBufferData(GL_ARRAY_BUFFER, bunny.normals.size() * sizeof(glm::vec3), &bunny.normals[0], GL_STATIC_DRAW);  // 3rd attribute buffer : normals 		glEnableVertexAttribArray(1); 		glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); 		glVertexAttribPointer( 			1,                                // attribute 			3,                                // size 			GL_FLOAT,                         // type 			GL_FALSE,                         // normalized? 			0,                                // stride 			(void*)0                          // array buffer offset 		);      if( ! prog.compileShaderFromFile("shader/basic1.vert",GLSLShader::VERTEX) )     {         printf("Vertex shader failed to compile!\n%s",                prog.log().c_str());         exit(1);     }     if( ! prog.compileShaderFromFile("shader/basic1.frag",GLSLShader::FRAGMENT))     {         printf("Fragment shader failed to compile!\n%s",                prog.log().c_str());         exit(1);     }      prog.bindAttribLocation(0, "VertexPosition");     prog.bindAttribLocation(1, "VertexNormal");      if( ! prog.link() )     {         printf("Shader program failed to link!\n%s",                prog.log().c_str());         exit(1);     }     if( ! prog.validate() )     {         printf("Program failed to validate!\n%s",                prog.log().c_str());         exit(1);     }     prog.use(); }

設(shè)置uniform變量:

void CGL::setUniform() {     mat4 model = mat4(1.0f);     //model *= glm::rotate(model, -35.0f, vec3(1.0f,0.0f,0.0f));    // model *= glm::rotate(model, 35.0f, vec3(0.0f,1.0f,0.0f));     mat4 view = glm::lookAt(vec3(0.0f,5.0f,10.0f), vec3(-1.0f,2.0f,0.0f), vec3(0.0f,1.0f,0.0f));     mat4 projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);     mat4 mv = view * model;      prog.setUniform("Kd", 0.6f, 0.9f, 0.9f);     prog.setUniform("Ld", 1.0f, 1.0f, 1.0f);     prog.setUniform("LightPosition", view * vec4(-5.0f,20.0f,15.0f,1.0f) );     prog.setUniform("ModelViewMatrix", mv);     prog.setUniform("NormalMatrix",mat3( vec3(mv[0]), vec3(mv[1]), vec3(mv[2]) ));     prog.setUniform("MVP", projection * mv);  }

頂點shader:

#version 400 layout (location = 0) in vec3 VertexPosition;   layout (location = 1) in vec3 VertexNormal;    out vec3 LightIntensity;  uniform vec4 LightPosition; // Light position in eye coords. uniform vec3 Kd;            // Diffuse reflectivity uniform vec3 Ld;            // Diffuse light intensity  uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 MVP;   void main() { 	vec3 tnorm = normalize(NormalMatrix * VertexNormal); 	vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition, 1.0); 	vec3 s = normalize(vec3(LightPosition - eyeCoords)); 	LightIntensity = Ld * Kd * max(dot(s,tnorm),0.0); 	gl_Position = MVP * vec4( VertexPosition, 1.0); }

片段shader:

#version 400  in vec3 LightIntensity; out vec4 gl_FragColor;  void main(void) { 	gl_FragColor = vec4(LightIntensity, 1.0); }

最后就是渲染了:

glDrawArrays(GL_TRIANGLES, 0, bunny.vertices.size() );

跳出渲染循環(huán)的時候,別忘了刪除緩存內(nèi)容:

void CGL::clean() {     glDeleteBuffers(1, &vertexbuffer); 	prog.deleteProgram(); 	glDeleteVertexArrays(1, &VertexArrayID); }

運行結(jié)果如下:

OpenGL進階(十二) - 基礎(chǔ)著色(Shading)

ADS 著色(AmbientDiffuseSpecular Shading)

     ADS就是上面提到的光照模型,也稱做Phong reflection model 或者 Phong Shading model。這時候光照的計算模型就是:

OpenGL進階(十二) - 基礎(chǔ)著色(Shading)

主要需要修改的是頂點shader,在著色器中實現(xiàn)對光照效果的計算:

basic.vert

#version 400 layout (location = 0) in vec3 VertexPosition;   layout (location = 1) in vec3 VertexNormal;    out vec3 LightIntensity;  struct LightInfo{ 	vec4 Position; 	vec3 La; 	vec3 Ld; 	vec3 Ls; };  struct MaterialInfo{ 	vec3 Ka; 	vec3 Kd; 	vec3 Ks; 	float Shininess; };  uniform LightInfo Light; uniform	MaterialInfo Material;  uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP;   void getEyeSpace(out vec3 norm, out vec4 position) { 	norm =  normalize(NormalMatrix * VertexNormal); 	position = ModelViewMatrix * vec4(VertexPosition, 1.0); }  vec3 phongModel(vec4 position, vec3 norm) { 	vec3 s = normalize(vec3(Light.Position - position)); 	vec3 v = normalize(-position.xyz); 	vec3 r = reflect(-s, norm); 	vec3 ambient = Light.La * Material.Ka; 	float sDotN = max(dot(s, norm), 0.0); 	vec3 diffuse = Light.Ld * Material.Kd * sDotN; 	vec3 spec = vec3(0.0);  	 	if(sDotN >0.0) 		spec = Light.Ls * Material.Ks * pow(max(dot(r,v), 0.0), Material.Shininess); 	return ambient + diffuse + spec; }  void main() { 	vec3 eyeNorm; 	vec4 eyePosition; 	getEyeSpace(eyeNorm, eyePosition); 	LightIntensity = phongModel(eyePosition, eyeNorm); 	 	gl_Position = MVP * vec4( VertexPosition, 1.0); 	//gl_Position = vec4( VertexPosition, 1.0); }

注意這里在shader中使用了function,使用的方式和c語言中非常相似,但是返回值的定義有些不同,而且不能有重復(fù)定義,即使在不同的作用域。

程序中只要設(shè)置好相關(guān)的uniform就可以了:

void CGL::setUniform() {     mat4 model = mat4(1.0f);     mat4 view = glm::lookAt(vec3(0.0f,5.0f,10.0f), vec3(-1.0f,2.0f,0.0f), vec3(0.0f,1.0f,0.0f));     mat4 projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);     mat4 mv = view * model;      prog.setUniform("Material.Kd", 0.9f, 0.5f, 0.3f);     prog.setUniform("Light.Ld", 1.0f, 1.0f, 1.0f);     prog.setUniform("Material.Ka", 0.9f, 0.5f, 0.3f);     prog.setUniform("Light.La", 0.4f, 0.4f, 0.4f);     prog.setUniform("Material.Ks", 0.8f, 0.8f, 0.8f);     prog.setUniform("Light.Ls", 1.0f, 1.0f, 1.0f);     prog.setUniform("Material.Shininess", 100.0f);     prog.setUniform("ModelViewMatrix", mv);     prog.setUniform("NormalMatrix",mat3( vec3(mv[0]), vec3(mv[1]), vec3(mv[2]) ));     prog.setUniform("MVP", projection * mv);  }

渲染一下。

OpenGL進階(十二) - 基礎(chǔ)著色(Shading)

由于關(guān)于著色的計算是在頂點shader中完成的,所以也可以稱為逐頂點著色(per-vertex lighting)

雙面著色 two-sided shading

    當(dāng)渲染的模型是完全封閉的時候,模型中所有面的背面都是不可見的,但是,如果模型有開口的話就比較麻煩了,渲染的結(jié)果很可能并不正確,因為面的法線并不正確。這時候就需要將法線反向,然后根據(jù)反向后的法線來計算光強。

    直接渲染帶洞的model,結(jié)果如下:

OpenGL進階(十二) - 基礎(chǔ)著色(Shading)

修改一下shader:

basic.vert

#version 400 layout (location = 0) in vec3 VertexPosition;   layout (location = 1) in vec3 VertexNormal;    //out vec3 LightIntensity; out vec3 frontColor; out vec3 backColor;  struct LightInfo{ 	vec4 Position; 	vec3 La; 	vec3 Ld; 	vec3 Ls; };  struct MaterialInfo{ 	vec3 Ka; 	vec3 Kd; 	vec3 Ks; 	float Shininess; };  uniform LightInfo Light; uniform	MaterialInfo Material;  uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP;   void getEyeSpace(out vec3 norm, out vec4 position) { 	norm =  normalize(NormalMatrix * VertexNormal); 	position = ModelViewMatrix * vec4(VertexPosition, 1.0); }  vec3 phongModel(vec4 position, vec3 norm) { 	vec3 s = normalize(vec3(Light.Position - position)); 	vec3 v = normalize(-position.xyz); 	vec3 r = reflect(-s, norm); 	vec3 ambient = Light.La * Material.Ka; 	float sDotN = max(dot(s, norm), 0.0); 	vec3 diffuse = Light.Ld * Material.Kd * sDotN; 	vec3 spec = vec3(0.0);  	 	if(sDotN >0.0) 		spec = Light.Ls * Material.Ks * pow(max(dot(r,v), 0.0), Material.Shininess); 	return ambient + diffuse + spec; }  void main() { 	vec3 eyeNorm; 	vec4 eyePosition; 	getEyeSpace(eyeNorm, eyePosition); 	frontColor = phongModel(eyePosition, eyeNorm); 	backColor = phongModel(eyePosition, -eyeNorm); 	gl_Position = MVP * vec4( VertexPosition, 1.0); 	//gl_Position = vec4( VertexPosition, 1.0); }

basic.frag

#version 400  //in vec3 LightIntensity; in vec3 frontColor; in vec3 backColor; out vec4 gl_FragColor;  void main(void) { 	if(gl_FrontFacing) 	gl_FragColor = vec4(frontColor, 1.0); 	else 	gl_FragColor = vec4(backColor, 1.0); }

在basic.vert中計算出內(nèi)部和外部的片段顏色,然后在片段著色器中根據(jù) gl_FrontFacing 來判斷面是否為背面,然后分開著色,再渲染一下

OpenGL進階(十二) - 基礎(chǔ)著色(Shading)

平坦著色 flat shading

    這個著色方式是想對于Gouraud Shading (高洛德著色/高氏著色)來說的。

     Gouraud Shading 在游戲中使用最廣泛的一種著色方式。它可對3D模型各頂點的顏色進行平滑、融合處理,將每個多邊形上的每個點賦以一組色調(diào)值,同時將多邊形著上較為順滑的漸變色,使其外觀具有更強烈的實時感和立體動感,不過其著色速度比平面著色慢得多。

     在shader中要實現(xiàn)flat shading非常簡單,只要在 in out 參數(shù)的前面加上flat關(guān)鍵字就可以了。

baisic .vert

...... flat out vec3 LightIntensity; ....

basic.frag

... flat in vec3 LightIntensity; ...

 渲染一下,對比兩種效果:

OpenGL進階(十二) - 基礎(chǔ)著色(Shading)

 相關(guān)下載

Stanford dragon

Stanford bunny

程序源碼

參考

OpenGL 4.0 Shading Language Cookbook

OpenGL 編程指南

OpenGL Shading Language

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當(dāng)前文章:OpenGL進階(十二)-基礎(chǔ)著色(Shading)-創(chuàng)新互聯(lián)
URL分享:http://jinyejixie.com/article46/decoeg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、微信公眾號品牌網(wǎng)站制作、域名注冊電子商務(wù)、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)
通河县| 萍乡市| 鄂州市| 甘谷县| 新河县| 申扎县| 新兴县| 保山市| 安塞县| 五河县| 定西市| 奉新县| 大同市| 阳春市| 卓尼县| 大连市| 诏安县| 福泉市| 鲜城| 南岸区| 铁岭市| 汝城县| 隆林| 葫芦岛市| 达州市| 乐山市| 西宁市| 台北县| 旬阳县| 凤冈县| 饶平县| 涪陵区| 全南县| 安国市| 岳普湖县| 龙陵县| 高青县| 辽宁省| 调兵山市| 峡江县| 织金县|