日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > php教程 > 渲染世界的OPENGL<11>模擬光線

渲染世界的OPENGL<11>模擬光線

來源:程序員人生   發(fā)布時(shí)間:2016-10-22 13:57:52 閱讀次數(shù):2420次

(1)簡單漫反射光
3D圖形利用最普遍的光線類型就是漫射光。漫反射光是1種經(jīng)過平面反射的定向光,其強(qiáng)度和光線在表面的入射角成正比。
要肯定1個(gè)指定定點(diǎn)上的光線的強(qiáng)度,我們需要兩個(gè)向量。第1個(gè)向量就是光源的方向。某些光源技術(shù)只是提供1個(gè)指向光源的向量,我們稱之為定向光。對所有頂點(diǎn)來講指向光源的,都是同1個(gè)向量。
注意:這類方式在光源距離被照亮物體非常遠(yuǎn)的情況下是非常適用的。如果照明朝碼提供的是光源的位置,那末我們必須在著色器中使用經(jīng)過變換的視覺坐標(biāo)光源位置減去頂點(diǎn)位置。從而肯定指向光源的向量。

表面法線
我們在漫反射光源中需要的第2個(gè)向量是表面法線。經(jīng)過某個(gè)假想平面上方的頂點(diǎn),并與這個(gè)平面成直角的1條線段,這條線就成為法向量。
注意,每一個(gè)頂點(diǎn)都要制定1個(gè)法向量。但是我們其實(shí)不希望每一個(gè)法向量都和多邊形的表面精確垂直。我們可以將這些表面近似看成是平的,但是結(jié)果會(huì)得到1個(gè)鋸齒狀或多面的表面,我們可以通過“調(diào)劑”表面法線使平面多邊形表面平滑,從而得到平滑表面的錯(cuò)覺。

頂點(diǎn)照明
頂點(diǎn)上光的強(qiáng)度通過接收到光源的向量和表面法線的向量點(diǎn)乘積來計(jì)算。兩個(gè)向量也需要是單位長度,而點(diǎn)乘積將會(huì)返回1個(gè)+⑴之間的值。當(dāng)表面法線和光照向量指向同1個(gè)方向的時(shí)候,將會(huì)出現(xiàn)1個(gè)1值的點(diǎn)乘積。當(dāng)兩個(gè)向量指向相反的方向的時(shí)候,則會(huì)返回⑴,。當(dāng)兩個(gè)向量相互成90度的時(shí)候,返回的點(diǎn)乘積為0,。這個(gè)+⑴之間的值實(shí)際上是這兩個(gè)向量之間夾角的余弦值。
正值意味著光線落在頂點(diǎn)上,這個(gè)值越接近1,則光照效果越強(qiáng),越接近0,那末光照效果越弱。
我們可以用點(diǎn)乘積的值和頂點(diǎn)的1個(gè)色彩值相乘,得到1個(gè)基于頂點(diǎn)光線強(qiáng)度的光照色彩值。在頂點(diǎn)之間對這些色彩值進(jìn)行平滑的著色,有時(shí)候被稱作頂點(diǎn)照明(vertex lighting)或背景著色(Gouraud shading)。在GLSL中,點(diǎn)乘積的部份比較簡單。

float intensity=dot(vSurfaceNormal, vLightDirection);

(2)點(diǎn)光源漫反射著色器

// Simple Diffuse lighting Shader // Vertex Shader // Richard S. Wright Jr. // OpenGL SuperBible #version 130 //首先是頂點(diǎn)渲染器 // 輸入頂點(diǎn)和法向量 in vec4 vVertex; in vec3 vNormal; //注意:典型情況下,表面法線作為1個(gè)頂點(diǎn)屬性提交,表面法線必須 //進(jìn)行旋轉(zhuǎn)從而使得他的方向在視覺空間以內(nèi)。我們常常傳遞1個(gè)法向矩陣 //這個(gè)值只包括模型視圖矩陣的旋轉(zhuǎn)份量。 //可以通過GLTransformation當(dāng)中的GetNormalMatrix函數(shù)返回這個(gè)值。 // 設(shè)置每一個(gè)批次 uniform vec4 diffuseColor; //球體的色彩 uniform vec3 vLightPosition;//光源位置的視覺坐標(biāo) uniform mat4 mvpMatrix;//模型視圖投影矩陣 uniform mat4 mvMatrix;//模型視圖矩陣 uniform mat3 normalMatrix;// // 片斷程序所需要的色彩,經(jīng)過平滑著色的色彩值。 smooth out vec4 vVaryingColor; void main(void) { // 得到視覺坐標(biāo)系的表面法線向量 vec3 vEyeNormal = normalMatrix * vNormal; // 得到視覺坐標(biāo)系的頂點(diǎn)坐標(biāo) vec4 vPosition4 = mvMatrix * vVertex; vec3 vPosition3 = vPosition4.xyz / vPosition4.w; // 得到光源的向量 vec3 vLightDir = normalize(vLightPosition - vPosition3); // 得到點(diǎn)乘積所得到的漫反射強(qiáng)度 float diff = max(0.0, dot(vEyeNormal, vLightDir)); // 強(qiáng)度乘以漫反射色彩,得到漫反射光線色彩 vVaryingColor.rgb = diff * diffuseColor.rgb; vVaryingColor.a = diffuseColor.a; // 最后對多邊形進(jìn)行變換,讓模型透視投影矩陣對當(dāng)前 //頂點(diǎn)進(jìn)行變換。 gl_Position = mvpMatrix * vVertex; }

點(diǎn)渲染shader程序,在主程序工程文件下,以vp格式的文件存在。

#version 130 out vec4 vFragColor; smooth in vec4 vVaryingColor; void main(void) { //將點(diǎn)著色器當(dāng)中的輸出vVaryingColor直接分配給輸出 //片斷色彩。 vFragColor = vVaryingColor; }

片斷著色器如上,只需要對其的片斷色彩進(jìn)行賦值就能夠了。

#pragma comment(lib,"GLTools.lib") #include <GLTools.h> // OpenGL toolkit #include <GLMatrixStack.h> #include <GLFrame.h> #include <GLFrustum.h> #include <GLGeometryTransform.h> #include <StopWatch.h> #include <GL/glut.h> GLFrame viewFrame; GLFrustum viewFrustum; GLTriangleBatch sphereBatch; GLMatrixStack modelViewMatrix; GLMatrixStack projectionMatrix; GLGeometryTransform transformPipeline; GLShaderManager shaderManager; GLuint diffuseLightShader; // The diffuse light shader GLint locColor; // The location of the diffuse color GLint locLight; // The location of the Light in eye coordinates GLint locMVP; // The location of the ModelViewProjection matrix uniform GLint locMV; // The location of the ModelView matrix uniform GLint locNM; // The location of the Normal matrix uniform //任務(wù):設(shè)置背景色彩 //加載渲染框架、加載渲染器程序代碼、得到統(tǒng)1值的location void SetupRC(void) { // 背景色彩的設(shè)置 glClearColor(0.3f, 0.3f, 0.3f, 1.0f); //遮擋剔除和深度測試 glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); shaderManager.InitializeStockShaders(); viewFrame.MoveForward(4.0f); // 創(chuàng)造1個(gè)球體 gltMakeSphere(sphereBatch, 1.0f, 26, 13); //加載渲染框架,同時(shí)加載渲染器代碼,并且將兩個(gè)基本點(diǎn)的屬性傳入到頂點(diǎn)著色器中。 diffuseLightShader = shaderManager.LoadShaderPairWithAttributes("DiffuseLight.vp", "DiffuseLight.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal"); //對統(tǒng)1值的取值,得到對應(yīng)的統(tǒng)1值的位置 locColor = glGetUniformLocation(diffuseLightShader, "diffuseColor"); locLight = glGetUniformLocation(diffuseLightShader, "vLightPosition"); locMVP = glGetUniformLocation(diffuseLightShader, "mvpMatrix"); locMV = glGetUniformLocation(diffuseLightShader, "mvMatrix"); locNM = glGetUniformLocation(diffuseLightShader, "normalMatrix"); } // Cleanup void ShutdownRC(void) { } // 任務(wù):硬編碼需要傳入渲染器的兩個(gè)值、激活shader程序、對對應(yīng)的統(tǒng)1值矩陣進(jìn)行賦值 void RenderScene(void) { static CStopWatch rotTimer; // 清除當(dāng)前色彩緩沖區(qū)和深度緩沖區(qū)的數(shù)據(jù) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //對模型視圖矩陣壓入視圖幀 modelViewMatrix.PushMatrix(viewFrame); modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f); //硬編碼需要傳入渲染器程序當(dāng)中的值 GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f }; GLfloat vDiffuseColor[] = { 0.0f, 0.0f, 1.0f, 1.0f }; //激活shader程序 glUseProgram(diffuseLightShader); //對對應(yīng)的屬性進(jìn)行賦值 glUniform4fv(locColor, 1, vDiffuseColor); 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()); sphereBatch.Draw(); modelViewMatrix.PopMatrix(); glutSwapBuffers(); glutPostRedisplay(); } void ChangeSize(int w, int h) { // Prevent a divide by zero if (h == 0) h = 1; // Set Viewport to window dimensions 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); } /////////////////////////////////////////////////////////////////////////////// // Main entry point for GLUT based programs 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("Simple Diffuse Lighting"); 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; }

主程序,對漫反射渲染器的使用和操作。
注意1個(gè)常常出現(xiàn)的毛病:在設(shè)置著色器統(tǒng)1值以后,和對幾何圖形進(jìn)行渲染之前做進(jìn)1步修改。注意:glUniform函數(shù)其實(shí)不會(huì)將1個(gè)對這些數(shù)據(jù)的援用復(fù)制到著色器。這個(gè)函數(shù)會(huì)將實(shí)際數(shù)據(jù)復(fù)制到著色器中。

(3)ADS光照模型
ADS代表:Ambient環(huán)境光、Diffuse漫反射、Specular鏡面光。它遵守1個(gè)簡單的原則,物體有3種材質(zhì)屬性,環(huán)境光反射,漫反射,鏡面反射。這些屬性都是分配的色彩值,更明亮的色彩代表更高的反射量。光源也有這3種相同的屬性。這些屬性都是分配的色彩值,更明亮的色彩代表更高的反射量。光源也有這3種相同的屬性。一樣是分配的色彩值,表示光源的亮度。終究的頂點(diǎn)色彩就是光照和材質(zhì)的這3個(gè)屬性相互影響的總和。

環(huán)境光
環(huán)境光不來自任何特定的方向,來自某個(gè)光源,但是光線卻是在房間或場景當(dāng)中4處反射,沒有方向可言。
由于環(huán)境光所照耀的物體在所有方向的表面都是均勻照亮的。我們可以把環(huán)境光看成是利用到每一個(gè)光源的全局“照明”因子。這中光照份量確切非常接近環(huán)境中源自光源的散射光。
由環(huán)境光所照耀的物體在所有方向的表面都是均勻照亮的,我們可以把環(huán)境光看成利用到每一個(gè)光源的全局“照明”因子。這類光照份量確切非常接近環(huán)境中源自光源的散射光。
為了計(jì)算環(huán)境光源對終究頂點(diǎn)色彩的影響,環(huán)境光材質(zhì)的性質(zhì)由環(huán)境光的值來度量,這個(gè)值產(chǎn)生對環(huán)境色彩的影響。在GLSL著色器當(dāng)中,環(huán)境光的具體實(shí)現(xiàn)以下:

uniform vec3 vAmbientMaterial; uniform vec3 vAmbientLight; vec3 vAmbientColor = vAmbientMaterial * vAmbientLight;

漫射光
漫射光是光源的定向份量,也是我們前面的示例光照著色器的主題。在著色器當(dāng)中的代碼以下:

uniform vec3 vDiffuseMaterial; uniform vec3 vDiffuseLight; float fDotProduct = max(0.0, dot(vNormal, vLightDir)); vec3 vDiffuseColor = vDiffuseMaaterial * vDiffuseLight * fDotProduct;

鏡面光
鏡面光具有非常強(qiáng)的方向性,但是他的反射角度非常鋒利,僅僅沿著特定的方向反射。高強(qiáng)度的鏡面光趨向于在它所照耀的表面上構(gòu)成1個(gè)亮點(diǎn),成為鏡面亮點(diǎn)。由于高度方向性本質(zhì),根據(jù)視察者的位置不同,鏡面光乃至有可能看不到。聚光燈和太陽都是產(chǎn)生很強(qiáng)的鏡面光的例子,不過他們固然必須是照耀在1個(gè)光亮的物體。
首先我們必須找到被表面法線反射的向量和反向的光線向量。隨后這兩個(gè)向量的點(diǎn)乘積將會(huì)取“反光度”次冪。反光度越大,鏡面反射高光越小。
利用GLSL所實(shí)現(xiàn)的功能以下:

uniform vec3 vSpecularMaterial; uniform vec3 vSpecularLight; float shininess=128f; vec3 vReflection= reflect(-vLightDir, vEyeNormal); fSpec = pow(EyeReflectionAngle, shininess); vec3 vSpecularColor= vSpecularLight*vSpecularMaaterial*fSpec;

注意,和其他參數(shù)1樣,反光度參數(shù)也能夠是統(tǒng)1值,最高的鏡面指數(shù)設(shè)置為128,大于這個(gè)數(shù)字,這個(gè)值將會(huì)逐步減弱。
注意,頂點(diǎn)終究的色彩可以像下面這樣進(jìn)行計(jì)算:
vVertexColor=vAmbientColor+vDiffuseColor+vSpecularColor;

// ADS Point lighting Shader // Vertex Shader // Richard S. Wright Jr. // OpenGL SuperBible #version 130 // 輸入的數(shù)據(jù),依然是點(diǎn)坐標(biāo)和點(diǎn)的法向量 in vec4 vVertex; in vec3 vNormal; // 設(shè)置批次 uniform vec4 ambientColor; uniform vec4 diffuseColor; uniform vec4 specularColor; uniform vec3 vLightPosition; uniform mat4 mvpMatrix; uniform mat4 mvMatrix; uniform mat3 normalMatrix; // 終究傳遞給片元渲染器的color smooth out vec4 vVaryingColor; void main(void) { // 得到視覺坐標(biāo)系的法向量 vec3 vEyeNormal = normalMatrix * vNormal; // 得到視覺坐標(biāo)系的坐標(biāo) vec4 vPosition4 = mvMatrix * vVertex; vec3 vPosition3 = vPosition4.xyz / vPosition4.w; // 得到光源向量 vec3 vLightDir = normalize(vLightPosition - vPosition3); // 點(diǎn)乘得到1個(gè)漫反射強(qiáng)度 float diff = max(0.0, dot(vEyeNormal, vLightDir)); // 強(qiáng)度乘以漫反射色彩 vVaryingColor = diff * diffuseColor; // 在此基礎(chǔ)上加上環(huán)境光 vVaryingColor += ambientColor; // 鏡面光 //得到光源的反射向量 vec3 vReflection = normalize(reflect(-vLightDir, vEyeNormal)); //得到反射角的cos值 float spec = max(0.0, dot(vEyeNormal, vReflection)); if(diff != 0) { float fSpec = pow(spec, 128.0); vVaryingColor.rgb += vec3(fSpec, fSpec, fSpec); } //終究利用幾何變換 gl_Position = mvpMatrix * vVertex; }

ADS的頂點(diǎn)渲染器代碼如上。

#version 130 out vec4 vFragColor; smooth in vec4 vVaryingColor; void main(void) { vFragColor = vVaryingColor; }

片元著色器如上。

(4)Phong著色

3角形之間的不連續(xù)會(huì)致使上面所渲染的球體會(huì)產(chǎn)生亮線星光的效果。這類不連續(xù)則是由于色彩值在空間中進(jìn)行的是線性插值的緣由。亮線就是兩個(gè)獨(dú)立3角形之間的縫隙。
解決這類效果的1種方法叫做Phong著色。我們不在頂點(diǎn)之間進(jìn)行色彩插值,而是在頂點(diǎn)之間進(jìn)行表面法線插值,這就是所謂的Phong著色。
Phong著色會(huì)致使片元著色器中作的工作大大提高,由于片斷著色器的履行次數(shù)將會(huì)比頂點(diǎn)程序的履行次數(shù)多很多。

// ADS Point lighting Shader // Vertex Shader // Richard S. Wright Jr. // OpenGL SuperBible #version 130 //輸入每一個(gè)頂點(diǎn)和每一個(gè)頂點(diǎn)的法線 in vec4 vVertex; in vec3 vNormal; uniform mat4 mvpMatrix; uniform mat4 mvMatrix; uniform mat3 normalMatrix; uniform vec3 vLightPosition; // 片斷程序色彩 smooth out vec3 vVaryingNormal; smooth out vec3 vVaryingLightDir; void main(void) { // 獲得表面法線的視覺坐標(biāo) vVaryingNormal = normalMatrix * vNormal; // 獲得頂點(diǎn)位置的視覺坐標(biāo) vec4 vPosition4 = mvMatrix * vVertex; vec3 vPosition3 = vPosition4.xyz / vPosition4.w; // 獲得到光源的方向 vVaryingLightDir = normalize(vLightPosition - vPosition3); // 最后對多邊形進(jìn)行變換 gl_Position = mvpMatrix * vVertex; }

Phong頂點(diǎn)著色器,把具體的操作幾近都轉(zhuǎn)移到片元著色器上了。

#version 130 out vec4 vFragColor; uniform vec4 ambientColor; uniform vec4 diffuseColor; uniform vec4 specularColor; smooth in vec3 vVaryingNormal; smooth in vec3 vVaryingLightDir; void main(void) { // 點(diǎn)乘得到漫反射的強(qiáng)度 float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir))); // 用強(qiáng)度去乘以漫反射色彩將色彩設(shè)置為1.0 vFragColor = diff * diffuseColor; // 增加環(huán)境光 vFragColor += ambientColor; // 鏡面光 vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal))); float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); if(diff != 0) { float fSpec = pow(spec, 128.0); vFragColor.rgb += vec3(fSpec, fSpec, fSpec); } }

如上所示為片元著色器,大量的操作從頂點(diǎn)著色器轉(zhuǎn)移到片元著色器當(dāng)中,但是代碼幾近完全沒有改變,僅僅轉(zhuǎn)移了計(jì)算位置。這樣算是高質(zhì)量渲染了,會(huì)影響性能。
注意:1個(gè)著色器性能優(yōu)化的常規(guī)原則:將盡量多的處理進(jìn)程移出片元著色器而放入頂點(diǎn)著色器。

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 成人av在线网站 | 成人h视频在线观看 | 中文字幕电影在线观看 | 久久精品免费观看 | 99精品在线视频播放 | 国产综合精品一区二区三区 | 亚洲91精品 | 国产精品免费播放 | 国内精品国产成人国产三级粉色 | 国产69精品久久久久777 | 日本一区二区三区在线观看视频 | 日韩精品www | 天堂在线中文字幕 | 中文字幕不卡在线观看 | 91精品国产综合久久久久久 | 高清久久久 | 国产综合欧美 | 高清日韩av | 欧美综合在线视频 | 亚洲综合国产 | 一区二区三区视频在线 | 91久久久久久久久久久久久 | 国产成人久久 | 日韩免费 | 精品成人av | 国产成人精品久久二区二区91 | 日本免费大全免费网站视频 | 色区综合 | 日韩三级电影在线观看 | 国产精品久久久久久久岛一牛影视 | 99视频在线播放 | 蜜乳av一区 | av黄在线| 日本久久精品视频 | 九九精品在线 | 亚洲最新av| 国产99久久精品 | 成人一区二区三区四区 | 欧美多人在线 | 亚洲欧美另类在线 | 日韩毛片免费视频一级特黄 |