GLSL核心课程---纹理图像

GLSL(OpenGL 着色器语言)全面详解 摘要: GLSL(OpenGL着色语言)是一种专为OpenGL设计的高级着色器语言,用于在GPU上执行图形渲染任务。其核心功能包括顶点变换、光照计算、纹理采样等,支持从基础2D渲染到复杂3D效果。GLSL经历了多个版本迭代,从1.0的基础功能到4.0+的曲面细分、计算着色器及光线追踪扩展,逐步增强灵活性与性能。 GLSL语法基于C语言,支持基础数据类型(如float、vec3)、复合类型(如矩阵、采样器)及流程控制。着色器类型包括顶点着色器(几何变换)、片段着色器(颜色计算)、几何着色器(图元生成)、曲面细 阅读详情

大多数时候我们会将一幅纹理图像应用到模型上,或多或少就像壁纸一样。有时候纹理还可以看成是数据,不是颜色值。纹理坐标提供了在图像和模型之间的映射关系。在我们着色器中处理使用纹理之前我们需要在我们的OpenGL应用程序中做一些设置步骤。在这一节中,我们将覆盖一下经典纹理用法案例。

OpenGL

在我们着色器中使用纹理的第一步就是需要创建一个OpenGL纹理对象。一个通用的用法就是我们同样需要从文件中加载图像数据来添加到纹理中,如果你不确定如何做这一步,那么请看这一页的介绍。

在着色器中需要设置一个一致变量来储存纹理单元。注意,着色器接收的是纹理单元而不是纹理名字。OpenGL提供了多个单元,因此我们在一个着色器中使用多个纹理。纹理单元有效数据是GL_MAX_COMBIEND_TEXTURE_IMAGE_UNITS

让我们假定在着色器中定义一个叫做texUnit的一致变量。同样假定我们仅仅只有一个纹理,因此我们将绑定到纹理单元0.

OpenGL应用程序这一端,在设置的步骤,我们需要得到一致变量texUnit的位置。到目前为止OpenGL是将texUnit定义成整型变量。因此,假定变量p存储GLSL程序的名字,下面的代码得到位置:

GLint texUnitLoc = glGetUniformLocation(p, “texUnit”);

如果提供给着色器的纹理单元总是跟我们在应用程序设置的一样。房子我们不得不经常修改纹理单元。为了设置变量texUnit为纹理单元0我们需要这么写:

glProgramUniformli(p, texUnitLoc, 0);

绘制实现绑定纹理到纹理单元。因此,如果我们假定texture1D是纹理单元(由glGenTextures创建)和纹理是2D,我们可以这么写:

glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_2D, texture1D);

后面我们将绑定到VAOs和调用glDraw*命令。

GLSL

现在,让我们回到GLSL这一端。首先必须定义一个变量texUnit。这个变量定义成sampler*类型。Samplers是一个不透明类型,比如说,它们不能像常规变量那样处理,它们的用法在函数中有限制,必须适当使用。采样器处理的纹理是在OpenGL应用程序端定义的,输入函数可以从纹理数据中返回值。每个纹理类型都有一个合适的采样类型,实际上,就像一个纹理模板GL_TEXTURE_2D,那么采样类型会sampler2D

为了处理纹理我们需要两个元素:纹理单元,和纹理坐标。在这里有很多函数来处理纹理数据。其中的很多都是用来查询,其他一些提供纹理数据,让我们从一些查询开始。

一个通用的着色器可以处理纹理通过它们的大小。大小信息(宽度和高度)可以通过一致变量来提供给着色器。另外一个选项就是使用textureSize函数。这个函数返回的纹理在x, y, z分量的大小,而w是在纹理数组或者立方体纹理的索引。这个函数同样可以使用mipmap级数,在这种情况下上面所有的信息就是相对于查询mipmap级数信息。

纹理mipmap级数大小可以有textureQueryLevels来查询。这个函数可以返回在纹理中(从OpenGL4.3有效)有效的mipmap计算数目。

Mipmap级数,或者结合mipmap等级,可以在特定片段使用textureQueryLod获取。这个函数返回一个vec2其中的x分量表示将会被使用的等级和相应的比例。实际上x=3.25然后等级3将会贡献75%和等级425%

我们可以这个动作,参考下面的代码:

#version 420

uniform sampler2D texUnit;

out vec4 outputF;

void main()

{

vec2 res = textureQueryLod(texUnit, VertexIn.texCoord.xy);

if(res.x == 0)

outputF = vec4(1.0, 0.0, 0.0, 0.0);

else if(res.x < 1)

outputF = vec4(0.0, 1.0, 0.0, 0.0);

else if(res.x < 2)

outputF = vec4(0.0, 0.0, 1.0, 0.0);

else if(res.x < 3)

outputF = vec4(0.0, 1.0, 1.0, 0.0);

else if(res.x < 4)

outputF = vec4(1.0, 0.0, 1.0, 0.0);

else if(res.x < 5)

outputF = vec4(1.0, 1.0, 0.0, 0.0);

else if(res.x < 6)

outputF = vec4(0.5, 1.0, 0.0, 0.0);

else if(res.x < 7)

outputF = vec4(0.0, 1.0, 0.5, 0.0);

}

结果就像下面的图示一样:

检索纹理数据

为了处理检索纹理数据给我们的模型着色我们使用两个函数:texturetexelFetch。第一个函数使用01的纹理坐标,或者纹理坐标是重复情况下的小数部分。这些都是相对坐标。取回,另外一个方面,使用整数纹理坐标,就像直线和像素列。不能执行线性过滤,一个单一的纹理数据被取回。

一旦我们得到纹理数据,我们可以输出作为最终的颜色,或者跟反射强度计算混合。下面的图展示了上面的情况(左边:取代,右边:混合)


纹理颜色同样也可以像素材质混合。实际上,方向光着色器结合纹理可以像下面这么写:

顶点着色器:纹理坐标被添加到顶点属性中。顶点着色器仅仅传递而已。

#version 330

layout (std140) uniform Matrices{

mat4 m_pvm;

mat4 m_viewModel;

mat3 m_normal;

};

layout(std140) uniform Lights{

vec3 l_dir;

};

in vec4 position;

in vec3 normal;

in vec2 texCoord;

out Data{

Vec3 normal;

Vec4 eye;

Vec2 texCoord;

}DataOut;

void main()

{

DataOut.eye = m_viewModel * position;

DataOut.normal = normalize(m_normal * normal);

DataOut.texCoord = texCoord;

gl_Position = m_pvm * position;

}

片段着色器:添加一个采样器。纹理坐标用来实验函数texture来检索纹理数据。

#version 330

Layout(std140) uniform Material{

Vec4 diffuse;

Vec4 ambient;

Vec4 specular;

Float shininess;

};

Layout(std140) uniform Lights{

Vec3 l_dir;

};

In Data{

Vec4 eye;

Vec3 normal;

Vec2 texCoord;

}DataIn;

Uniform sampler2D texUnit;

Out vec4 colorOut;

Void main()

{

Vec4 spec = vec4(0.0);

Vec3 n = normalize(DataIn.normal);

Vec3 e = normalize(DataIn.eye);

Float intensity = max(0.0, dot(n, l_dir));

If(intensity > 0.0)

{

Vec3 h = normalize(l_dir + e);

Float intSpec = max(0.0, dot(h, n));

Spec = specular * pow(intSpec, shininess);

}

Vec4 texColor = texture(texUnit, DataIn.texCoord);

Vec4 diffColor = intensity * diffuse * texColor;

Vec4 ambColor = ambient * texColor;

colorOut = max(diffColor + spec , ambColor);

}

注意,仅仅只有漫反射和环境光颜色跟纹理相混合。镜面光是不受纹理影响的。

源代码和Visual Studio 2010工程可以在这里下载。注意,你必须有DevlL才能运行这个demo。

注意

如何采样器被定义成数组,那么采样器必须使用整型索引来取得动态一致值。这就意味着在运行的着色器中的所有实例索引值必须是常量。

下面的代码是可以的,因为我们总是使用同一个索引。

uniform int anIndex;

uniform sampler2D myTexture[3];

in vec2 texCoord;

void main()

{

...

color = texture(myTexture[anIndex],  texCoord);

....

}

下面我们呈现出一个如何错误的例子。我们想支持如果屏幕y坐标小于一个固定值让它旋转一个纹理,如果不是则选择另外一个纹理。

uniform int anIndex;

uniform sampler2D myTexture[3];

in vec2 texCoord;

void main()

{

...

if(gl_FragCoord.y > 100.0)

index = 0;

else

index = 1;

color = texture(myTexture[index], texCoord);

...

}

英语地址

本文永久地址:http://www.arcosu.com/post/index/95

GLSL 实现 FXAA 后处理效果 常见的抗锯齿手段有两种,一种是基于采样的 SSAA 和 MSAA,另一种是基于后处理的如 FXAA、TAA。效果上:SSAA > MSAA > TAA > FXAA (但是 TAA 会让部分玩家头晕,我自己用 FXAA 比较多)效率上:TAA > FXAA > MSAA > SSAATAA 和 FXAA 的效率差距其实很小,并且基于后处理的 AA 要比前一种效率高很多。这些抗锯齿选项基本是每个游戏的标配了。 阅读详情

相关推荐

学习threejs,使用自定义GLSL 着色器,生成漂流的3D能量球

本文详细介绍如何基于threejs在三维场景中自定义GLSL 着色器,生成漂流的3D能量球,亲测可用。希望能帮助到您。一起学习,加油!加油!

我哎GIS博客 3195

ShaderJoy —— “马赛克”的实现【GLSL

参考自:http://tech.it168.com/n/2007-03-29/200703291522292_3.shtml和http://blog.csdn.net/simpledrunk/article/details/17170965 原图: ”圆形” 效果图1 : “圆形”效果2: 片元着色器代码: uniform sampler2...

ShaderJoy 的兴趣技术杂货铺 6136

Opengl纹理采样

是在着色器中使用纹理坐标,从纹理中获取对应像素颜色值(texel)的过程。:一个图像,通常为 2D,但也可以是 1D、3D、立方体图等。着色器中只能采样在片元着色器、几何着色器、计算着色器等阶段。:纹理采样器变量,链接到 OpenGL 纹理单元。必须启用对应纹理对象,并设置好环绕和过滤参数。:在着色器中根据纹理坐标提取纹理颜色的过程。:纹理坐标,通常传自顶点着色器。,用于表示纹理图像中的位置。注:本文参考自chatgpt。:二维坐标,通常范围在。,表示纹理该坐标位置的。

积累点滴,保持自我 934

《OpenGL编程指南》 笔记六 纹理(二)

文章目录第六章 纹理6.9 纹理视图6.10 压缩纹理6.11 滤波6.11.1 线性滤波6.11.2 使用和生成mipmap6.11.3 计算mipmap级别6.11.4 mipmap细节层次控制6.12 高级纹理查询函数6.12.1 显示细节层次6.12.2 显示梯度设置6.12.3 偏移后的纹理获取6.12.4 投影纹理6.12.5 着色器中的纹理查询6.12.6 收集纹素6.12.7 合并...

wwhx27的博客 1469

优化OpenGLSL.texelFetch锯齿问题,让我想起一道阿里面试题。

OpenGLSL.texelFetch锯齿问题,让我想起当年阿里达摩院的一道面试题,而且实际操作编程题。

vx number:zzr_admin,拉入技术交流群。 1551

Shadow Map 原理和改进

shadow map基础及基本改进方法

ronintao的专栏 4万+

GLSL纹理Shader编程实战详解

回顾整篇文章,你会发现:🔥 纹理编程的本质,是一场精心设计的“数据迁移工程”。从磁盘文件 → CPU内存 → GPU显存 → 片段着色器 → 屏幕像素,每一步都需要精确对接。任何一个环节出错(比如UV没传、纹理单元没设对、参数配置失误),都会导致最终画面异常。但也正是这种底层可控性,赋予了开发者极大的创作自由。你可以:实现卡通渲染、热成像、X光透视等风格化效果构建地形系统、材质分层、动态贴图更新结合FBO做离屏渲染、后期处理、阴影贴图。

weixin_42153793的博客 1080

终极GLSL纹理处理指南:从PNG到MP4、HDR的完整解决方案

GLSL纹理处理是现代图形编程的核心技能,而glslViewer正是实现这一目标的完美工具。这个基于控制台的GLSL沙盒让开发者能够轻松加载和处理各种格式的纹理文件,包括PNG、MP4视频、HDR高动态范围图像等。无论你是想要创建动态视觉效果,还是处理复杂的图像数据,glslViewer都能提供强大的支持。 ## 🔥 为什么选择glslViewer进行纹理处理? glslViewer是一个轻

gitblog_00831的博客 617

Manim纹理系统:图像纹理与材质管理

Manim(Mathematical Animation Engine)是一个强大的数学动画引擎,其纹理系统为创建逼真的视觉效果提供了坚实基础。纹理系统通过GLSL着色器和Python对象相结合的方式,实现了高效的图像纹理映射和材质管理。 ## 核心架构 ### 纹理渲染管线 Manim的纹理渲染遵循现代图形渲染管线: ```mermaid flowchart TD A[Image...

gitblog_00228的博客 620

GLSL核心课程---纹理坐标

纹理坐标通常用作如何将一个一张图片贴到表面上。然而纹理坐标并不是限制执行这种贴图。纹理坐标本身同样也可以用作绘画模型。在这里我们用两个例子来说明纹理坐标如何使用。 第一步就是使纹理坐标在我们的着色器有效。纹理坐标仅仅是又一个属性变量,就像法向量一样。因此在应用程序中,我们需要像这样处理,比如,我们需要添加包含纹理坐标的包含其他属性的顶点数组对象的缓冲区(请看这一节来了解更多属性细节)。 在顶点

smsmn的专栏 3636

学习threejs,使用自定义GLSL 着色器,实现粒子特效

本文详细介绍如何基于threejs在三维场景中构建的动态 3D 粒子系统,使用 Tailwind CSS 设置样式,并通过自定义 GLSL 着色器进行增强。具有交互式图案过渡、摄像机控制和动画切换,可提供身临其境的视觉体验。亲测可用。希望能帮助到您。一起学习,加油!加油!

我哎GIS博客 1145

Imogen高级技巧:使用GLSL计算着色器创建复杂纹理效果

想要制作令人惊艳的纹理效果却不知从何入手?Imogen作为一款强大的GPU纹理生成器,通过GLSL计算着色器让你轻松实现专业级纹理创作。无论你是游戏开发者、视觉设计师还是纹理艺术家,掌握Imogen的GLSL计算着色器技巧将大幅提升你的工作效率和创作质量。😊 ## 🔥 为什么选择Imogen进行纹理创作? Imogen是一个基于GPU/CPU的节点式纹理生成工具,支持GLSL、C和Pyth

gitblog_00800的博客 392

OpenGL纹理采样器(Sampler)与纹理对象(Texture)到底啥关系?从GLSL的texture()调用说起

本文深入解析OpenGL中纹理采样器(Sampler)与纹理对象(Texture)的协同机制,从GLSL的texture()函数调用出发,揭示两者在三维图形渲染中的核心作用。通过详细代码示例和参数说明,帮助开发者理解纹理数据的存储与采样策略的控制,提升渲染效率与效果。

weixin_30299709的博客 361

GLSL Texture 开源项目教程

GLSL Texture 开源项目教程 本教程将引导您了解并使用 GLSL Texture 这一开源项目,它旨在简化GLSL纹理处理过程。我们将逐一探讨其核心组件,包括项目的目录结构、启动文件以及配置文件,以帮助您快速上手。 1. 项目目录结构及介绍 GLSL Texture项目遵循了典型的GitHub仓库结构,以下是主要目录和它们的简要说明: glslTexture/ │ ├── src/ ...

gitblog_00443的博客 925

Cesium 自定义材质性能对比:Canvas渐变纹理 vs GLSL着色器实现

本文对比了Cesium中实现立体墙渐变效果的两种技术方案:Canvas渐变纹理GLSL着色器。通过详细代码实现和性能测试数据,分析了两种方案在开发复杂度、运行性能、动态更新能力等方面的优劣,为开发者提供了针对不同场景的技术选型建议。

lvwenwen 475

GLSL(OpenGL 着色器语言)基础语法

GLSL语法类似 语言,但更适合GPU并行计算。✅顶点着色器主要进行坐标变换。✅片元着色器主要计算像素颜色。✅变量修饰符 in、out、uniform 控制数据流。✅向量、矩阵 计算是GLSL核心,优化GPU性能。

笔记的博客 2216
上一篇: GLSL核心课程---纹理图像
下一篇: 使用几何着色器来实现绘制模型轮廓线
smsmn
博客等级 码龄17年 65粉丝 126原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值