【计算机图形学】shading(着色/渲染)

1.一个简单的光照明模型(Blinn-Phong反射模型)

在这里插入图片描述

1.1漫反射
在这里插入图片描述
在这里插入图片描述
漫反射与观测视角无关。
1.2镜面反射
在这里插入图片描述
在这里插入图片描述
原本是看观测角和镜面反射角的方向一致程度,但因为镜面反射方向是很难求的,而半程向量有手就行。所以我们取一个近似。。
在这里插入图片描述
p值越大,高光点越小(高光点就是镜面反射的体现)

1.3环境光
在这里插入图片描述
大胆假设每个点都有一个基础光照,我们称之为环境光。。

3个光合在一起就是这个模型
在这里插入图片描述

2.着色频率(Shading Frequencies)

2.1平面着色(flat shading)
对每一个三角形着色
三角形面是平的-一个法向量
•不适用于光滑的表面
2.2高洛德着色(Gouraud shading)
对每个顶点着色
从三角形的顶点插入颜色
•每个顶点都有一个法向量(怎么做?)
考虑周围四个平面的法向量取平均值
在这里插入图片描述

2.3着色每个像素(Phong shading)
•插值法向量跨越每个三角形
•在每个像素计算完整的着色模型
•不是Blinn-Phong反射模型
通过顶点法向量进行插值或用重心坐标。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.纹理映射

每个3D表面点在2D图像(纹理)中都有一个位置。
在这里插入图片描述
3.1纹理放大
a.采取最近点策略
b.最近四个双线性插值策略
c.最近16个三线性插值策略
在这里插入图片描述
3.2纹理缩小
在这里插入图片描述
出现一个像素覆盖多个纹理的情况就会出现需要缩小纹理的情况
超采样可以实现但代价很高。
我们采用mipmap的方法
在这里插入图片描述
cost仅为原本样本的三分之一
在这里插入图片描述
根据像素点在纹理上的位置比确定D值的大致大小(估算)
在这里插入图片描述
在这里插入图片描述
三线性插值:
三线性滤波的原理很简单,就是对原本双线性插值的基础上再加一层对mipmap的采样。这里就不多说了。
在这里插入图片描述
因为会mipmap是正方形取值,难免会有不规则问题。。
各向异性过滤

在这里插入图片描述
EWA滤波被广泛的认为是纹理过滤(texture filtering)算法中最好的算法之一。它会追踪当前像素的纹理坐标对于屏幕空间坐标的微分。
EWA滤波参考:
https://zhuanlan.zhihu.com/p/105167411

纹理的许多用途
在现代gpu中,纹理=内存+范围查询(过滤)
•将数据带入片段计算的通用方法
许多应用程序也会用到
•环境照明
•存储microgeometry
•过程纹理
•固体模型
•体绘制
•……

4.环境光图

我们可以用一个水晶球来收集环境光
在这里插入图片描述
当然,也可以用立方体。
矢量沿着这个方向映射到正方体点。
立方体使用了6个正方形纹理贴图。
在这里插入图片描述
这样可以使扭曲变少。
在这里插入图片描述

5.纹理可以影响阴影!

因为纹理不必只代表颜色,它还可以存储高度/法线信息,这就是凹凸/法线贴图,用来伪造详细的几何图形。
在这里插入图片描述5.1 凹凸贴图(Bump Mapping)

添加表面细节而不添加更多的三角形
•扰动表面法线每像素
(只适用于阴影计算)
•由纹理定义的每个texel的“高度偏移”
那么如何修改法向量?
在这里插入图片描述起始n=(0,1);
开始扰动之后dp= c * [h(p+1) - h§]
n(p ) = (-dp, 1).normalized()//归一化
在这里插入图片描述

如果是在三维空间会怎么样呢?
起始n=(0,0,1)
开始扰动后
dp/du = c1 * [h(u+1) - h(u)]
dp/dv = c2 * [h(v+1) - h(v)]
n = (-dp/du, -dp/dv, 1).normalized()

5.2位移贴图(Displacement mapping)-一个更先进的方法
-使用与碰撞映射相同的纹理
-实际移动顶点
在这里插入图片描述
效果明显好一些

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本文将介绍计算机图形学中的着色Shading)技术,包括着色频率、图形管线、纹理映射等知识点,并提供部分代码示例。 ## 着色频率 计算机图形学中的着色可以分为两种频率,分别是顶点着色和像素着色。 顶点着色(Vertex Shading)是在顶点级别对图形进行着色的过程,即在图形的每个顶点上计算颜色值,然后通过插值计算出整个图形的颜色。顶点着色通常用于处理顶点属性,如位置、法向量和颜色等。 像素着色(Pixel Shading)是在像素级别对图形进行着色的过程,即对图形的每个像素计算颜色值。像素着色通常用于处理纹理映射、阴影效果、反射和折射等。 ## 图形管线 图形管线(Graphics Pipeline)是计算机图形学中的一个重要概念,它是将输入的几何形状转化为最终图像的过程,通常包括以下几个阶段: 1. 顶点输入:将输入的顶点数据传入图形管线。 2. 顶点着色:在顶点级别对图形进行着色。 3. 图元装配:将顶点组装成图元,如点、线、三角形等。 4. 光栅化:将图元转化为像素,并计算像素在屏幕上的位置。 5. 像素着色:对图形的每个像素进行着色。 6. 输出合成:将所有像素合成成最终的图像。 以下是一个简单的图形管线示例: ```c++ // 顶点着色器 void vertexShader(in vec3 position, out vec4 color) { // 计算顶点颜色 color = vec4(1.0, 0.0, 0.0, 1.0); // 将顶点位置传递给下一个阶段 gl_Position = vec4(position, 1.0); } // 像素着色器 void pixelShader(in vec4 color, out vec4 fragmentColor) { // 直接输出顶点颜色 fragmentColor = color; } // 主程序 int main() { // 顶点数据 vec3 vertices[] = { vec3(-1.0, -1.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0) }; // 图元数据 GLuint indices[] = {0, 1, 2}; // 创建着色器程序 GLuint program = createProgram(vertexShader, pixelShader); // 获取顶点着色器输入位置的位置 GLuint positionLocation = glGetAttribLocation(program, "position"); // 创建顶点数组对象 GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // 创建顶点缓冲区对象 GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 将顶点数据传递给顶点着色器 glEnableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); // 创建索引缓冲区对象 GLuint ibo; glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 渲染图元 glUseProgram(program); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); // 销毁着色器程序、缓冲区对象和顶点数组对象 glDeleteProgram(program); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDeleteVertexArrays(1, &vao); return 0; } ``` ## 纹理映射 纹理映射(Texture Mapping)是一种基于图像的着色技术,它可以在三维模型表面上贴上图片,从而增强模型的真实感和细节。 纹理映射通常包括以下几个步骤: 1. 加载纹理图像:从文件中加载纹理图像,并将其存储在计算机内存中。 2. 创建纹理对象:将纹理图像传递给图形硬件,并创建一个纹理对象。 3. 纹理坐标计算:计算每个顶点在纹理图像中对应的位置,通常使用二维纹理坐标表示。 4. 纹理采样:在纹理图像中根据纹理坐标采样像素颜色,并将其作为顶点颜色。 5. 顶点着色:使用顶点颜色进行顶点着色。 以下是一个简单的纹理映射示例: ```c++ // 顶点着色器 void vertexShader(in vec3 position, in vec2 texCoord, out vec2 vTexCoord) { // 将纹理坐标传递给下一个阶段 vTexCoord = texCoord; // 将顶点位置传递给下一个阶段 gl_Position = vec4(position, 1.0); } // 像素着色器 uniform sampler2D texture; void pixelShader(in vec2 vTexCoord, out vec4 fragmentColor) { // 在纹理图像中采样像素颜色 vec4 texel = texture2D(texture, vTexCoord); // 输出纹理像素颜色 fragmentColor = texel; } // 主程序 int main() { // 顶点数据 vec3 vertices[] = { vec3(-1.0, -1.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0) }; // 纹理坐标数据 vec2 texCoords[] = { vec2(0.0, 0.0), vec2(0.5, 1.0), vec2(1.0, 0.0) }; // 图元数据 GLuint indices[] = {0, 1, 2}; // 加载纹理图像 GLuint texture = loadTexture("texture.png"); // 创建着色器程序 GLuint program = createProgram(vertexShader, pixelShader); // 获取顶点着色器输入位置和纹理坐标的位置 GLuint positionLocation = glGetAttribLocation(program, "position"); GLuint texCoordLocation = glGetAttribLocation(program, "texCoord"); // 创建顶点数组对象 GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // 创建顶点缓冲区对象 GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 将顶点数据传递给顶点着色器 glEnableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); // 创建纹理坐标缓冲区对象 GLuint tbo; glGenBuffers(1, &tbo); glBindBuffer(GL_ARRAY_BUFFER, tbo); glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW); // 将纹理坐标数据传递给顶点着色器 glEnableVertexAttribArray(texCoordLocation); glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); // 创建索引缓冲区对象 GLuint ibo; glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 渲染图元 glUseProgram(program); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUniform1i(glGetUniformLocation(program, "texture"), 0); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); // 销毁着色器程序、缓冲区对象、纹理对象和顶点数组对象 glDeleteProgram(program); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &tbo); glDeleteBuffers(1, &ibo); glDeleteTextures(1, &texture); glDeleteVertexArrays(1, &vao); return 0; } ``` 以上是计算机图形学着色技术的简单介绍,希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值