精华内容
下载资源
问答
  • OpenGL 镜面反射 IBL

    2021-03-19 23:25:16
    OpenGL镜面反射 IBL镜面反射 IBL简介蒙特卡洛积分和重要性采样低差异序列GGX 重要性采样捕获预过滤 mipmap 级别预过滤卷积的伪像高粗糙度的立方体贴图接缝预过滤卷积的亮点 镜面反射 IBL简介 在上一节教程中,我们...

    镜面反射 IBL简介

    在上一节教程中,我们预计算了辐照度图作为光照的间接漫反射部分,以将 PBR 与基于图像的照明相结合。在本教程中,我们将重点关注反射方程的镜面部分:
    在这里插入图片描述
    卷积的第一部分被称为预滤波环境贴图,它类似于辐照度图,是预先计算的环境卷积贴图,但这次考虑了粗糙度。因为随着粗糙度的增加,参与环境贴图卷积的采样向量会更分散,

    展开全文
  • OPENGL 镜面效果源代码

    2017-12-15 14:33:05
    计算机图形学opengl 模板缓存镜面效果 基于ios,xcode开发
  • OpenGL镜面效果

    千次阅读 2015-08-30 19:14:11
    我们会给每个模型贴上纹理图,纹理图的使用上一节已经讲过了,我们会实现一个镜面的效果,如上图,每个模型下面都有一个像是通过镜子反射的模型一样。 其实做法很简单,我们只需要把原来的视口矩阵反转如下的代码 ...

    我们这一节的效果图如下:



    我们会给每个模型贴上纹理图,纹理图的使用上一节已经讲过了,我们会实现一个镜面的效果,如上图,每个模型下面都有一个像是通过镜子反射的模型一样。

    其实做法很简单,我们只需要把原来的视口矩阵反转如下的代码

    modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);

    然后把改变多边形的正面,OpenGl默认的多边形的正面是逆时针的,我们在这里改为顺时针,如下代码

    glFrontFace(GL_CW);

    然后绘制镜面中的物体,绘制完成后把多边形的正面再改回逆时针的

    glFrontFace(GL_CCW);

    然后我们绘制地板,并且和刚才绘制的镜面中的物体进行混合操作

    最后我们再绘制地面上的物体,这样就实现的镜面效果


    下面是代码实现

    首先是需要包含的头文件 和全局变量

    #include <GLTools.h>
    #include <GLShaderManager.h>
    #include <GLFrustum.h>
    #include <GLBatch.h>
    #include <GLMatrixStack.h>
    #include <GLGeometryTransform.h>
    #include <StopWatch.h>
    
    #include <math.h>
    #include <stdio.h>
    
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    
    #define NUM_SPHERES 50
    GLFrame spheres[NUM_SPHERES];
    
    GLShaderManager		shaderManager;			
    GLMatrixStack		modelViewMatrix;	
    GLMatrixStack		projectionMatrix;		
    GLFrustum			viewFrustum;			
    GLGeometryTransform	transformPipeline;		
    GLFrame				cameraFrame;			
    
    GLTriangleBatch		torusBatch;
    GLTriangleBatch		sphereBatch;
    GLBatch				floorBatch;
    
    GLuint				uiTextures[3];


    然后是主函数main

    int main(int argc, char* argv[])
        {
    
    		//设置工作路径
    		gltSetWorkingDirectory(argv[0]);
    		//初始化glut
    		glutInit(&argc, argv);
    		//申请一个带有双缓冲区,颜色缓冲区的窗口
    		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    		//窗口大小
    		glutInitWindowSize(800, 600);
    		//窗口名字
    		glutCreateWindow("OpenGL SphereWorld");
    		//窗口大小改变时的回调函数
    		glutReshapeFunc(ChangeSize);
    		//键盘按键响应函数
    		glutSpecialFunc(SpecialKeys);
    		//渲染的回调函数
    		glutDisplayFunc(RenderScene);
    
    		GLenum err = glewInit();
    		if (GLEW_OK != err) {
    			fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
    			return 1;
    		}
    
    		//初始化函数
    		SetupRC();
    		//主函数循环
    		glutMainLoop();
    		//循环结束后释放内存
    		ShutdownRC();
    
    		return 0;
        }


    然后是窗口改变大小时的回调函数ChangeSize

    void ChangeSize(int nWidth, int nHeight)
        {
    		//设置视口大小
    		glViewport(0, 0, nWidth, nHeight);
    		//将视图变换矩阵 和 模型 变换矩阵统一管理起来
    		transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    		//设置视口变换矩阵
    		viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);
    		//设置模型变换矩阵
    		projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    		//设置视图变换矩阵
    		modelViewMatrix.LoadIdentity();
    	}


    然后是响应键盘方向键的函数SpecialKeys

    void SpecialKeys(int key, int x, int y)
        {
    		float linear = 0.1f;
    		float angular = float(m3dDegToRad(5.0f));
    
    		if (key == GLUT_KEY_UP)
    			cameraFrame.MoveForward(linear);
    
    		if (key == GLUT_KEY_DOWN)
    			cameraFrame.MoveForward(-linear);
    
    		if (key == GLUT_KEY_LEFT)
    			cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    
    		if (key == GLUT_KEY_RIGHT)
    			cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
        }


    下面是初始化函数SetupRC

    void SetupRC()
        {
    		//初始化glew
    		glewInit();
    		//初始化着色器管理类
    		shaderManager.InitializeStockShaders();
    		//开启深度测试
    		glEnable(GL_DEPTH_TEST);
    		//开启剔除
    		glEnable(GL_CULL_FACE);
    		//清除后台缓存	
    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    	
    		// 初始化泳圈模型
    		gltMakeTorus(torusBatch, 0.4f, 0.15f, 40, 20);
    	
    		// 初始化小球模型
    		gltMakeSphere(sphereBatch, 0.1f, 26, 13);
    	
    		//初始化地板数据
    		GLfloat texSize = 10.0f;
    		floorBatch.Begin(GL_TRIANGLE_FAN, 4, 1);
    		floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    		floorBatch.Vertex3f(-20.0f, -0.41f, 20.0f);
    	
    		floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
    		floorBatch.Vertex3f(20.0f, -0.41f, 20.0f);
    	
    		floorBatch.MultiTexCoord2f(0, texSize, texSize);
    		floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
    	
    		floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
    		floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
    		floorBatch.End();
    	
    		// 创建3个纹理对象
    		glGenTextures(3, uiTextures);
    	
    		// 绑定纹理1对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
    		LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
    	
    		// 绑定纹理2对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
    		LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR, 
    					   GL_LINEAR, GL_CLAMP_TO_EDGE);
    	
    		// 绑定纹理3对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    		LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
    					   GL_LINEAR, GL_CLAMP_TO_EDGE);
                       
    		// 设置50个小球的位置
    		for(int i = 0; i < NUM_SPHERES; i++) 
    			{
    				GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
    				GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
    				spheres[i].SetOrigin(x, 0.0f, z);
    			}
        }

    下面是加载纹理图片的函数LoadTGATexture

    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;
    		//设置纹理环绕模式
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    		//设置纹理过滤模式
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
    		//开启紧密包装像素数据模式
    		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    		//生成纹理图片
    		glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
    					 eFormat, GL_UNSIGNED_BYTE, pBits);
    	
    		free(pBits);
    		//创建Mip贴图
    		if(minFilter == GL_LINEAR_MIPMAP_LINEAR || 
    		   minFilter == GL_LINEAR_MIPMAP_NEAREST ||
    		   minFilter == GL_NEAREST_MIPMAP_LINEAR ||
    		   minFilter == GL_NEAREST_MIPMAP_NEAREST)
    			glGenerateMipmap(GL_TEXTURE_2D);
                
    		return true;
    	}

    下面是具体绘制模型的函数DrawSongAndDance

    void DrawSongAndDance(GLfloat yRot)		// Called to draw dancing objects
    	{
    		static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    		static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
    	
    		// 得到光源位置
    		M3DVector4f	vLightTransformed;
    		M3DMatrix44f mCamera;
    		modelViewMatrix.GetMatrix(mCamera);
    		m3dTransformVector4(vLightTransformed, vLightPos, mCamera);
    	
    		// 绘制光源
    		modelViewMatrix.PushMatrix();
    		modelViewMatrix.Translatev(vLightPos);
    		shaderManager.UseStockShader(GLT_SHADER_FLAT, 
    									 transformPipeline.GetModelViewProjectionMatrix(),
    									 vWhite);
    		sphereBatch.Draw();
    		modelViewMatrix.PopMatrix();
        
    		//渲染50个静止的小球
    		glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    		for(int i = 0; i < NUM_SPHERES; i++) {
    			modelViewMatrix.PushMatrix();
    			modelViewMatrix.MultMatrix(spheres[i]);
    			shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
    										 modelViewMatrix.GetMatrix(),
    										 transformPipeline.GetProjectionMatrix(),
    										 vLightTransformed, 
    										 vWhite,
    										 0);
    			sphereBatch.Draw();
    			modelViewMatrix.PopMatrix();
    		}
    
    		modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
    		modelViewMatrix.PushMatrix();	// Saves the translated origin
    		modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    	
    		//绑定泳圈模型的纹理对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
    		//绘制泳圈模型
    		shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
    									 modelViewMatrix.GetMatrix(),
    									 transformPipeline.GetProjectionMatrix(),
    									 vLightTransformed, 
    									 vWhite,
    									 0);
    		torusBatch.Draw();
    		modelViewMatrix.PopMatrix(); // Erased the rotate
    	
    		modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    		modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    	
    		//绘制旋转的小球
    		glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    		shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
    									 modelViewMatrix.GetMatrix(),
    									 transformPipeline.GetProjectionMatrix(),
    									 vLightTransformed, 
    									 vWhite,
    									 0);
    		sphereBatch.Draw();
    	}

    下面是程序退出时执行的清理函数ShutdownRC

    void ShutdownRC(void)
        {
    		//释放纹理对象
    		glDeleteTextures(3, uiTextures);
        }


    基本上每一行代码都有注释,有哪里看不懂的童鞋,我们可以一起讨论 ):











    展开全文
  • OpenGL 镜面反射光

    千次阅读 2017-05-07 17:08:12
    背景 ...我们在计算环境光的时候,光的强度是唯一的影响因素。然后处理漫射光的时候...镜面反射时光以一定角度照射到物体表面,同时会在法线的另一侧对称的角度上反射出去,如果观察者刚好在反射光线的路径上那

    转载地址:http://www.2cto.com/kf/201611/561551.html

    背景

    我们在计算环境光的时候,光的强度是唯一的影响因素。然后处理漫射光的时候公式中加入了光的方向参数。镜面反射包含了上面所有的综合因素并且添加了一个新的元素:观察者的位置。镜面反射时光以一定角度照射到物体表面,同时会在法线的另一侧对称的角度上反射出去,如果观察者刚好在反射光线的路径上那么就会看到格外强烈的光线。

    镜面反射最终的结果是物体在从某个角度看上去会十分明亮,而移动开后这个光亮又会消失。现实中好的镜面反射的例子是金属物体,这些物体有时候看上去由于太亮了导致看不到他本来的颜色而是直接照向你眼睛的白色的亮光。但这种属性在其他的一些材料上是没有的(比如:木头)。很多东西根本不会发光,不管光源从什么角度照射以及观察者在什么位置。所以,镜面反射光的存在更取决于反射物体的材料性质而不是光源本身。

    现在看如何将观察者的位置加入到镜面反射光的计算当中,看下图:

    要注意五个因素:

    ‘I’ 是入射光

    ‘N’ 是表面法线

    ‘R’ 反射光,和入射光’I’关于法线对称,但方向相反

    ‘V’ 是从入射光和反射光交点处(入射点)到观察者眼睛的向量,表示观察者视线

    ‘α’ 反射光’R’和观察者视线’V’的夹角

    我们将使用夹角’α’来对镜面反射光现象进行建模。有一点可以看出当观察者视线和反射光重合时(夹角为0),反射光的强度最大。观察者慢慢从反射光’R’移开时,夹角慢慢变大,而我们希望随着角度增大反射光要慢慢衰弱。明显,这里又要使用差积运算来计算夹角’α’的余弦值了,这个值将作为计算镜面反射光公式的反射参数。当’α’为0时余弦值为1,这是我们反射参数的最大值。随着夹角’α’增大余弦值慢慢减小,直到夹角达到90度时就彻底没有镜面反射的效果了。当然,夹角大于90度时余弦值为负,也没有任何反射效果,也就是观察者不在反射光的路径范围内。

    我们要用到’R’和’V’来计算夹角’α’。’V’可以通过世界坐标系中观察者位置和光的入射点位置的差计算得到。camera已经在世界空间进行维护了,我们只需要将它的位置传给shader着色器。另外上面的图是经过简化了的模型,光在物体表面只有一个入射点(事实上不是,这里只是为了好分析)。事实上,整个三角形都被点亮了(假设它面向光源),因此我们要计算每一个像素的镜面反射效果(和漫反射光的计算一样)。我们必须要知道每个像素在世界空间的位置,这个不难:可以将顶点变换到世界空间,让光栅器对像素的世界空间位置进行插值并将结果传给片段着色器。事实上,这个和之前教程中对法线的处理操作是一样的。

    最后是要使用’I’向量(由应用传给shader)来计算反射光线’R’。如下图:

    首先要强调向量没有起点的概念,所有方向相同且长度相同的向量都是同一个向量。因此,图中将入射光向量’I’复制到表面下面位置向量本身是不变的。目标是求向量’R’,根据向量的加法,’R’等于’I’+’V’。’I’是已知的,所以我们要求’V’。注意法线’N’的反向向量为’-N’,计算’I’和’-N’的点积可以得到’I’在’-N’上的投影,这也是’V’的模长度的一半。另外’V’和’N’的方向是相同的,所以只要用计算的那个投影长度乘以单位向量’N’再乘以2就是向量’V’了。用公式简单表示如下:

    明白这个数学公式后可以说一个相关的知识点:GLSL提供了一个叫做’reflect’的内部函数就是做的上面这个计算。可以看下面这个函数在shader中的用法。这里得出计算镜面反射的最终公式:

    开始先是将光的颜色和物体表面的颜色相乘,这个和在计算环境光以及漫反射光时一样。得到的结果再和材料的镜面反射强度参数(’M’)相乘。如果材料没有反射性能,比如木头,那么镜面反射参数就为0,整个公式的结果也就为0了,而像金属这种发光材料镜面反射能力就会很强。之后再乘以光线和观察者视线夹角的余弦值,这也是最后一个调整镜面反射光强度的参数(‘镜面参数’或者叫做‘发光参数’)。镜面参数是用来增强加剧反射光区域边缘的强度的。下面的图片展示了镜面参数为1时的效果:

    下面的镜面参数为32:

    镜面反射能力也被认为是材料的一种属性,因此不同的物体会有不同的镜面反射能力值。

    源代码详解

    (lighting_technique.h:32)

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class LightingTechnique : public Technique
    {
    public :
    ...
         void SetEyeWorldPos( const Vector3f& EyeWorldPos);
         void SetMatSpecularIntensity( float Intensity);
         void SetMatSpecularPower( float Power);
     
    private :
    ...
         GLuint m_eyeWorldPosLocation;
         GLuint m_matSpecularIntensityLocation;
         GLuint m_matSpecularPowerLocation;
    }

    LightingTechnique类中有了三个新属性:眼睛(观察者)的位置、镜面反射强度和材料的镜面参数。这三个参数都是独立于光线本身的,因为当同一束光照到不同的材料上(比如:木头和金属)时会有不同的反射发光效果。目前对材料属性的的使用模型还是很局限的,同一个绘制回调的所有三角形会得到这些属性的一样的值。如果同一个模型的不同部分的三角形图元是不同的材料,这样就不合理了。在后面的教程中讲关于mesh网格的加载时我们会在一个模块中产生不同的镜面参数值并作为顶点缓冲器的一部分(而不是shader的一个参数),这样我们就可以在同一个绘制回调中使用不同的镜面光照参数来处理三角形图元。这里简单的使用一个shader参数就可以实现效果(当然可以尝试在顶点缓冲中添加不同的镜面强度参数然后在shader中获取来实现更复杂的镜面效果)。

    (lighting.vs:12)

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    out vec3 WorldPos0;
     
    void main()
    {
         gl_Position = gWVP * vec4(Position, 1.0 );
         TexCoord0 = TexCoord;
         Normal0 = (gWorld * vec4(Normal, 0.0 )).xyz;
         WorldPos0 = (gWorld * vec4(Position, 1.0 )).xyz;
    }

    上面顶点着色器多了最后一行代码,世界变换矩阵(之前用来变换法线的那个世界变换矩阵)这里用来将顶点的世界坐标传给片段着色器。这里有一个技术点是使用两个不同的矩阵来变换本地坐标提供的同一个顶点位置,并将结果独立的传递给片段着色器。经过完整的变换(world-view-projection变换)后结果传递给系统变量’gl_Position’,然后GPU负责将它变换到屏幕空间坐标系并用来进行实际的光栅化操作。局部变换到世界空间的结果传给了一个用户自定义的属性,这个属性在光栅化阶段被进行了简单的插值,所以片段着色器中激活的每一个像素都会提供它自己的世界空间位置坐标。这种技术很普遍也很有用。

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    (lighting.fs: 5 )
    in vec3 WorldPos0;
    .
    .
    .
    uniform vec3 gEyeWorldPos;
    uniform float gMatSpecularIntensity;
    uniform float gSpecularPower;
     
    void main()
    {
         vec4 AmbientColor = vec4(gDirectionalLight.Color * gDirectionalLight.AmbientIntensity, 1 .0f);
         vec3 LightDirection = -gDirectionalLight.Direction;
         vec3 Normal = normalize(Normal0);
     
         float DiffuseFactor = dot(Normal, LightDirection);
     
         vec4 DiffuseColor = vec4( 0 , 0 , 0 , 0 );
         vec4 SpecularColor = vec4( 0 , 0 , 0 , 0 );
     
         if (DiffuseFactor > 0 ) {
             DiffuseColor = vec4(gDirectionalLight.Color, 1 .0f) *
                 gDirectionalLight.DiffuseIntensity *
                 DiffuseFactor;
     
             vec3 VertexToEye = normalize(gEyeWorldPos - WorldPos0);
             vec3 LightReflect = normalize(reflect(gDirectionalLight.Direction, Normal));
             float SpecularFactor = dot(VertexToEye, LightReflect);
             if (SpecularFactor > 0 ) {
                 SpecularFactor = pow(SpecularFactor, gSpecularPower);
                 SpecularColor = vec4(gDirectionalLight.Color * gMatSpecularIntensity * SpecularFactor, 1 .0f);
             }
         }
     
         FragColor = texture2D(gSampler, TexCoord0.xy) * (AmbientColor + DiffuseColor + SpecularColor);
    }

    片段着色器中的变化是多了三个新的一致性变量,用来存储计算镜面光线的一些属性(像眼睛的位置、镜面光强度和镜面反射参数)。环境光颜色的计算和前面两篇教程中的计算一样。然后创建漫射光和镜面光颜色向量并初始化为0,之后只有当光线和物体表面的角度小于90度时颜色值才不为零,这个要通过漫射光参数来检查(和在漫射光教程中说的一样)。

    下一步要计算世界空间中从顶点位置到观察者位置的向量,这个通过观察者世界坐标和顶点的世界坐标相减计算得到,其中观察者的世界坐标是一个一致变量对于所有的像素点来说都一样。为了方便后面的点积操作这个向量要进行单位化。然后,使用内置的’reflect’函数就可以计算反射光向量了(当然也可以自行按照上面背景中介绍的手动计算)。’reflect’函数有两个参数:光线向量和物体表面法向量。注意这里使用的是最原始的射向物体表面的那个光源向量而不是用于漫射光参数计算的反向的光源向量(见上面图示)。然后计算镜面反射参数,也就是反射光和顶点到观察者那个向量的夹角余弦值(还是通过点积计算得到)。

    镜面反射效果只有在那个夹角小于90度时才看得到,所以我们要先检查点积的结果是否大于0。最后一个镜面颜色值是通过将光源颜色和材料的镜面反射强度以及材料镜面反射参数相乘计算得到。我们将镜面颜色值添加到环境光和漫射光颜色中来制造光颜色的整体效果。最后和从纹理中取样的颜色相乘得到最终的像素颜色。

    (tutorial19.cpp:134)

    ?
    1
    2
    3
    m_pEffect->SetEyeWorldPos(m_pGameCamera->GetPos());
    m_pEffect->SetMatSpecularIntensity( 1 .0f);
    m_pEffect->SetMatSpecularPower( 32 );

    镜面反射光颜色的使用很简单。在渲染循环我们得到了camera的位置(在世界空间中已经维护好了)并将它传给了LightingTechnique类。这里还设置了镜面反射强度和镜面参数。剩下的就由着色器来处理了。

    可以调整镜面反射的参数值以及光源的方向来看效果。当然为了找到可以看到镜面反射光效果的位置可能需要围着物体转一圈。


    展开全文
  • OPENGL镜面反射练习

    2018-03-28 18:31:35
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X #endif ...
    #include <glad\glad.h>
    #include <GLFW\glfw3.h>
    
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    
    #include "Shader.h"
    #include <iostream>
    
    const char* cubeVertexShaderSource = "#version 330 core\n"
    "layout(location = 0) in vec3 aPos;\n"
    "layout(location = 1) in vec3 aNormal;\n"
    "out vec3 Normal;\n"
    "out vec3 FragPos;\n"
    "uniform mat4 model;\n"
    "uniform mat4 view;\n"
    "uniform mat4 projection;\n"
    "void main(){\n"
    "Normal = aNormal;\n"
    "FragPos = vec3(model * vec4(aPos,1.0));\n"
    "gl_Position = projection * view * model * vec4(aPos,1.0);\n"
    "}\n"
    ;
    
    const char* cubeFragShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "in vec3 Normal;\n"
    "in vec3 FragPos;\n"
    "uniform vec3 lightPos;\n"
    "uniform vec3 lightColor;\n"
    "uniform vec3 objectColor;\n"
    "uniform vec3 viewPos;\n"
    "void main(){\n"
    "float ambientStrength = 0.1;\n"
    "vec3 ambient = ambientStrength * lightColor;\n"
    "vec3 normal = normalize(Normal);\n"
    "vec3 lightDir = normalize(lightPos - FragPos);\n"
    "float lightDiff = max(dot(normal,lightDir),0.0);\n"
    "vec3 lightUse = lightDiff * lightColor;\n"
    "float specularStrength = 0.5;\n"
    "vec3 viewDir = normalize(viewPos - FragPos);\n"
    "vec3 reflectDir = reflect(-lightDir, normal);\n"
    "float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);\n"
    "vec3 specular = specularStrength * spec * lightColor;"
    "vec3 result = (ambient + lightUse + specular) * objectColor;\n"
    "FragColor = vec4(result,1.0);\n"
    "}\n"
    ;
    
    const char* lightVertexShaderSource = "#version 330 core\n"
    "layout(location = 0) in vec3 aPos;\n"
    "uniform mat4 model;\n"
    "uniform mat4 view;\n"
    "uniform mat4 projection;\n"
    "void main(){\n"
    "gl_Position = projection * view * model * vec4(aPos,1.0);\n"
    "}\n"
    ;
    
    const char* lightFragShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main(){\n"
    "FragColor = vec4(1.0);\n"
    "}\n"
    ;
    
    const unsigned int SRC_WIDTH = 800;
    const unsigned int SRC_HEIGHT = 600;
    
    glm::vec3 cameraPos = glm::vec3(0.8f,0.7f,3.0f);
    glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
    glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
    
    glm::vec3 lightPosition = glm::vec3(1.0f,1.0f,1.0f);
    glm::vec3 lightColor = glm::vec3(1.0f);
    glm::vec3 objectColor = glm::vec3(0.5f, 0.5f, 0.3f);
    
    float zoom = 45.0f;
    float lastX = (float)(SRC_WIDTH/2.0f);
    float lastY = (float)(SRC_HEIGHT / 2.0f);
    float mouseSensitive = 0.1f;
    bool firstMouse = true;
    float yaw = -90.0f;
    float pitch = 0.0f;
    
    
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    void processInput(GLFWwindow *window);
    void mouse_callback(GLFWwindow* window, double xpos, double ypos);
    
    int main()
    {
    	glfwInit();
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    #ifdef __APPLE__
    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
    #endif
    	GLFWwindow* window = glfwCreateWindow(SRC_WIDTH, SRC_HEIGHT, "Zhongqi", NULL, NULL);
    	if (window == NULL)
    	{
    		std::cout << "Create Window Failed" << std::endl;
    		glfwTerminate();
    		return -1;
    	}
    
    	glfwMakeContextCurrent(window);
    	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    	glfwSetCursorPosCallback(window,mouse_callback);
    	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    	{
    		return -1;
    	}
    
    	glEnable(GL_DEPTH_TEST);
    
    	Shader cubeShader(cubeVertexShaderSource,cubeFragShaderSource);
    	Shader lightShader(lightVertexShaderSource,lightFragShaderSource);
    
    	float vertices[] = {
    		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    		0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    		0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    		0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    		-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    
    		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
    		0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
    		0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
    		0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
    		-0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
    		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
    
    		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    		-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    		-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    
    		0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
    		0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
    		0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
    		0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
    		0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
    		0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
    
    		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
    		0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
    		0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    		0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    		-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
    
    		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
    		0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
    		0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    		0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    		-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
    	};
    
    	unsigned cubeVAO, VBO;
    	glGenVertexArrays(1, &cubeVAO);
    	glGenBuffers(1, &VBO);
    	glBindVertexArray(cubeVAO);
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);
    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(0));
    	glEnableVertexAttribArray(0);
    	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    	glEnableVertexAttribArray(1);
    
    	unsigned int lightVAO;
    	glGenVertexArrays(1, &lightVAO);
    	glBindVertexArray(lightVAO);
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);
    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(0));
    	glEnableVertexAttribArray(0);
    
    	while (!glfwWindowShouldClose(window))
    	{
    		processInput(window);
    		glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    		cubeShader.use();
    		glm::mat4 model = glm::mat4();
    		glm::mat4 view;
    		glm::mat4 projection;
    		view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
    		projection = glm::perspective(glm::radians(zoom), (float)SRC_WIDTH / (float)SRC_HEIGHT, 0.1f, 100.0f);
    		cubeShader.setMat4("model", model);
    		cubeShader.setMat4("view", view);
    		cubeShader.setMat4("projection", projection);
    		cubeShader.setVec3("lightPos", lightPosition);
    		cubeShader.setVec3("lightColor",lightColor);
    		cubeShader.setVec3("objectColor",objectColor);
    		cubeShader.setVec3("viewPos",cameraPos);
    		glBindVertexArray(cubeVAO);
    		glDrawArrays(GL_TRIANGLES, 0, 36);
    
    		lightShader.use();
    		model = glm::translate(model, lightPosition);
    		model = glm::scale(model, glm::vec3(0.3f));
    		lightShader.setMat4("model", model);
    		lightShader.setMat4("view", view);
    		lightShader.setMat4("projection", projection);
    		glBindVertexArray(lightVAO);
    		glDrawArrays(GL_TRIANGLES, 0, 36);
    
    		glfwSwapBuffers(window);
    		glfwPollEvents();
    	}
    
    
    	glDeleteVertexArrays(1, &lightVAO);
    	glDeleteVertexArrays(1, &cubeVAO);
    	glDeleteBuffers(1, &VBO);
    
    	glfwTerminate();
    	return 0;
    }
    
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
    	glViewport(0, 0,width, height);
    }
    
    void processInput(GLFWwindow *window)
    {
    	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    		glfwSetWindowShouldClose(window, true);
    }
    
    void mouse_callback(GLFWwindow* window, double xpos, double ypos)
    {
    	if (firstMouse)
    	{
    		lastX = xpos;
    		lastY = ypos;
    		firstMouse = false;
    	}
    
    	float xoffset = xpos - lastX;
    	float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
    
    	lastX = xpos;
    	lastY = ypos;
    
    	xoffset *= mouseSensitive;
    	yoffset *= mouseSensitive;
    
    	yaw += xoffset;
    	pitch += yoffset;
    	if (pitch > 89.0f) pitch = 89.0f;
    	if (pitch < -89.0f) pitch = -89.0f;
    
    	glm::vec3 front;
    	front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
    	front.y = sin(glm::radians(pitch));
    	front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
    
    	cameraFront = glm::normalize(front);
    
    }

    效果图



    展开全文
  • opengl镜面反射

    千次阅读 2010-07-25 18:05:00
    但做镜面的反射不是让opengl自己去计算一个镜面的反射画面,而是把物件和反射面画出来后,再在反射面的那块区域把物件的倒影画出来。听起来不算简单,但难点却不是怎么画倒影,而是怎么把倒影限定在某块区域。要实现...
  • OPENGL镜面光反射

    千次阅读 2010-03-19 16:10:00
    要使物体能够根据视点的不同而看出来有光线移动的效果,我们需要加上镜面反射:由于镜面反射光的计算项=max{0,S.N}shininess*specularlight*specularmaterial,所以我们可以看出需要设置镜面反射指数GL_SHININESS,...
  • OpenGL ES 镜面光照

    2015-08-15 12:11:07
    * openGL分为三种光 * 环境光(全局光 ambient light) * 散射光(diffuse light) * 镜面光(specular light) */ public class MyLightingRenderer2 extends MyAbstractRenderer { public void onSurfaceCreated...
  • 前置:OpenGL基础19:法向量与漫反射 一、镜面光照 前面物体已经拥有了环境光和漫反射光,现在再加上镜面光照就完美了,镜面光照的效果是:当我们去看光被物体所反射的那个方向的时候,会看到一个高光 和镜面反射...
  • OpenGL Directional Lights II Time for the specular component of the OpenGL directional light. The lighting model used is the Blinn-Phong model, which is a simplification of the Phon...
  • OpenGL学习-基础光照之镜面光照 开发环境搭建参考:https://lexiaoyuan.blog.csdn.net/article/details/120059213 通用配置步骤 Visual Studio,创建一个新的空项目 复制glad.c文件到你的工程中 选中项目,右键...
  • OpenGL中设置光照的镜面反射效果

    千次阅读 2014-12-14 16:45:29
    OpenGL中设置光照的镜面反射效果  在上一篇笔记中,我们记述了光线的方向与多边形表面的角度计算关系,除此之外,我们还有光源的位置需要指定。我们在ChangeSize函数的内部指定光源的位置:  // 指定光源的...
  • C++ opengl 漫反射和镜面反射参数

    千次阅读 2018-07-24 21:14:00
    漫反射和镜面反射参数 开启光照后,物体表面的颜色:由 环境光+漫反射+镜面反射 组成 漫反射: glLightfv(GL_LIGHT0,GL_DIFFUSE,whiteColor); glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuseMat); 镜面反射: ...
  • OpenGL_16_镜面反射

    2017-03-24 18:51:00
    镜面反射包含了上面所有的综合因素并且添加了一个新的元素:观察者的位置。镜面反射时光以一定角度照射到物体表面,同时会在法线的另一侧对称的角度上反射出去,如果观察者刚好在反射光线的路径上那么就会看到格外...
  • android opengles光照效果-镜面

    千次阅读 2017-01-10 02:15:42
    表面光滑的物体,不只有漫反射,还有镜面反射效果,如玻璃球。镜面反射可以使用公式: 镜面光照结果=材质的反射系数 x 环境光强度 x power(max(0, dot(N, normalise(L + E))), shininess) N:法向量 L:光源向量 E:...
  • OpenGL 基于PBR的specular textured 镜面纹理先上图,再解答。完整主要的源代码源代码剖析 先上图,再解答。 完整主要的源代码 #include <glad/glad.h> #include <GLFW/glfw3.h> #include <stb_...
  • 大家好,接下来将为大家介绍OpenGL ES 3. 光照-镜面光。 现实世界中,当光滑表面被照射时会有方向很集中的反射光。这就是镜面光(Specular)。 与散射光最终强度仅依赖于入射光与被照射点法向量的夹角不同,镜面光...
  • 在现实世界中,如果我们用一面镜子去观察一盏灯,随着我们的移动,灯在镜子中的位置也会跟随移动,接下来我们就要把现实世界中的这个现象模拟到OpenGL中。由于这个现象和观察者有关系,所以需要计算观察向量和反射...
  • 教程19镜面反射光原文: http://ogldev.atspace.co.uk/www/tutorial19/tutorial19.htmlCSDN完整版专栏: http://blog.csdn.net/column/details/13062.html背景我们在...镜面反射包含了上面所有的综合因素并且添加了一个
  • 上一篇了解到的 Diffuse Lighting 漫反射光照 对比,Speculer Lighting 镜面高光需要添加一个新的变量 - 观察者的位置。 我们代码中观察者 就是 摄像机,所以就使用 摄像机 的位置坐标 替代 观察者的位置。
  • OpenGL学习之路17---- 镜面反射光

    千次阅读 2018-05-10 20:42:56
    代码放在github上 根据教程:ogldev一步步开始,记录学习历程 之前完成环境光和漫射光的学习。...镜面反射光是当光线以一定的角度照射到物体表面后,从法线的另一侧堆成的角度反射出去的光线 所...
  • OpenGL教程翻译 第十九课 镜面高光

    千次阅读 2015-09-29 11:31:07
    第十九课 镜面高光原文地址:...镜面反射光包含这些因素,并且增加一个新的因素——观察者位置。这样做的原因是当光线以某一角度照射到一个平面上时,他会以相同的角度反射出去(在法线的另一边)。如果观察
  • 镜面光逐顶点渲染效果 顶点shader attribute vec3 pos;//顶点坐标 attribute vec2 texcoord;//纹理坐标 attribute vec3 normal;//法线 uniform mat4 M;//模型矩阵 uniform mat4 P;//投影矩阵 uniform mat4 V;...
  • 但是在为光滑的金属物体建模时,为了使其显得更加逼真,仅仅使用环境光和漫反射光是不够的,还需要镜面光的效果。 镜面亮点 镜面光照和材料属性可以为物体表面添加光泽和亮斑的效果。当入射光与观察者的角度较...
  • OpenGL着色器程序解析--镜面反射光

    千次阅读 2018-06-20 15:38:57
    镜面反射包含了上面所有的综合因素并且添加了一个新的元素:观察者的位置。镜面反射时光以一定角度照射到物体表面,同时会在法线的另一侧对称的角度上反射出去,如果观察者刚好在反射光线的路径上那么就会看到格外...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,061
精华内容 1,624
关键字:

opengl镜面