如何使用OpenGL ES 2.0着色器执行以下图像处理任务?
我一直在敲Shadertoy - https://www.shadertoy.com/ - 最近,为了更多地了解OpenGL和GLSL.
据我所知,到目前为止,OpenGL用户首先必须准备要使用的所有几何体并配置OpenGL服务器(允许的光源数量,纹理存储等).一旦完成,用户就必须在OpenGL程序编译之前提供至少一个顶点着色器程序和一个片段着色器程序.
但是,当我查看Shadertoy上的代码示例时,我只看到一个着色器程序,并且大多数使用的几何图形似乎直接写入GLSL代码.
这是如何运作的?
我猜测顶点着色器已经预先准备好了,可编辑/样本着色器只是一个片段着色器.但是,这并没有解释一些更复杂的例子中的几何...
谁能解释Shadertoy是如何工作的?
我的代码以这种方式接近GLSL着色器管理,它创建每个着色器和相关程序并删除每个着色器和程序.我最近阅读了http://www.opengl.org/wiki/GLSL_Object,并指出:
由于附加到程序对象,着色器对象即使删除着色器对象也将继续存在.只有在系统不再附加到任何程序对象时(当用户要求删除它时),它才会被系统删除.
我是否正确得到这个,如果我glDeleteShader()
在链接到程序后调用着色器对象,我只需要跟踪程序?假设这一直是真的,这是安全的吗?
过去几周我一直在学习OpenGL,我在实现Phong着色器方面遇到了一些麻烦.尽管使用了smooth
限定符,但似乎在顶点之间没有插值.我在这里错过了什么吗?为了给予信用到期的信用,顶点和片段着色器的代码严重影响了OpenGL SuperBible第五版.我强烈推荐这本书!
顶点着色器:
#version 330
in vec4 vVertex;
in vec3 vNormal;
uniform mat4 mvpMatrix; // mvp = ModelViewProjection
uniform mat4 mvMatrix; // mv = ModelView
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
void main(void) {
vVaryingNormal = normalMatrix * vNormal;
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
vVaryingLightDir = normalize(vLightPosition - vPosition3);
gl_Position = mvpMatrix * vVertex;
}
Run Code Online (Sandbox Code Playgroud)
片段着色器:
#version 330
out vec4 vFragColor; …
Run Code Online (Sandbox Code Playgroud) 您填充值的变量是否决定了您正在使用的精度,等号的右侧?
例如,这里的精度说明符是否有任何意义上的区别:
gl_FragColor = lowp vec4(1);
Run Code Online (Sandbox Code Playgroud)
这是另一个例子:
lowp float floaty = 1. * 2.;
floaty = lowp 1. * lowp 2.;
Run Code Online (Sandbox Code Playgroud)
如果你采用一些浮点数,并从它们创建一个向量或矩阵,那么该向量或矩阵是否会采用您填充它的值的精度,或者这些值是否会转换为另一个精度级别?
我认为优化这个最好能回答这个问题:
dot(gl_LightSource[0].position.xyz, gl_NormalMatrix * gl_Normal)
Run Code Online (Sandbox Code Playgroud)
我的意思是,它是否需要走这么远,如果你想尽可能快,或者它有些无用吗?
lowp dot(lowp gl_LightSource[0].position.xyz, lowp gl_NormalMatrix * lowp gl_Normal)
Run Code Online (Sandbox Code Playgroud)
我知道你可以定义float的默认精度,并且这可以用于之后的向量和矩阵.假设为了教育的目的,我们之前已经定义了这个:
precision highp float;
Run Code Online (Sandbox Code Playgroud) 当您学习3D编程时,您会被教导从3个转换矩阵的角度来考虑它是最简单的:
模型矩阵.该矩阵对于每个模型都是独立的,它可以根据需要旋转和缩放对象,最后将其移动到3D世界中的最终位置."模型矩阵将模型坐标转换为世界坐标".
视图矩阵.对于大量对象(如果不是对于所有对象),该矩阵通常是相同的,并且它根据当前"摄像机位置"旋转并移动所有对象.如果您对相机拍摄3D场景进行成像,并且屏幕上呈现的内容是此相机捕获的图像,则相机的位置及其查看方向定义场景的哪些部分可见以及对象如何出现在捕获的图像上.在渲染单个帧时更改视图矩阵几乎没有理由,但实际上存在这些原因(例如,通过渲染场景两次并更改其间的视图矩阵,您可以在场景中创建一个非常简单但令人印象深刻的镜像) .通常,视图矩阵在绘制的两个帧之间仅改变一次."视图矩阵将世界坐标转换为眼睛坐标".
投影矩阵.投影矩阵决定这些3D坐标如何被映射到2D坐标,例如,如果存在应用于它们的透视(对象变得越小,它们离观察者越远)(正交投影).投影矩阵几乎没有变化.如果您渲染到窗口并且窗口大小已更改,或者您正在全屏渲染并且分辨率已更改,则可能必须更改,但是仅当新窗口大小/屏幕分辨率具有与之前不同的显示宽高比时.有一些疯狂的效果,你可能想要改变这个矩阵,但在大多数情况下,它对于整个程序的实时几乎是不变的."投影矩阵将眼睛坐标转换为屏幕坐标".
这对我来说很有意义.当然,总是可以将所有三个矩阵组合成单个矩阵,因为首先将矢量乘以矩阵A
然后乘以矩阵B
与将矢量乘以矩阵相同C
,其中C = B * A
.
现在,如果你看一下经典的OpenGL(OpenGL 1.x/2.x),OpenGL知道一个投影矩阵.然而,OpenGL不提供模型或视图矩阵,它只提供组合的模型视图矩阵.为什么?此设计强制您永久保存和恢复"视图矩阵",因为它将被应用于它的模型转换"破坏".为什么没有三个单独的矩阵?
如果你看一下新的OpenGL版本(OpenGL 3.x/4.x)并且你没有使用经典的渲染管道而是使用着色器(GLSL)自定义所有内容,那么根本就没有可用的矩阵,你必须定义自己的矩阵.大多数人仍然保留投影矩阵和模型视图矩阵的旧概念.为什么要这么做?为什么不使用三个矩阵,这意味着您不必永久保存和恢复模型视图矩阵,或者使用单个组合模型 - 视图 - 投影(MVP)矩阵,这可以节省顶点着色器中的矩阵乘法对于任何单个顶点渲染(毕竟这样的乘法也不是免费的).
因此,总结一下我的问题:在具有三个单独的矩阵或单个MVP矩阵的情况下,哪个优势具有组合的模型 - 视图矩阵以及单独的投影矩阵?
我一直在尝试使用OpenGL和GLSL编写Marching Cubes算法的两遍GPU实现,类似于GPU Gems 3第一章中详述的算法.但是,glDrawArrays
在我的第一次传球中的呼叫始终失败了GL_INVALID_OPERATION
.
我查找了所有可以找到的文档,并发现这些条件glDrawArrays
可以抛出该错误:
GL_INVALID_OPERATION
如果非零缓冲区对象名称绑定到已启用的数组或GL_DRAW_INDIRECT_BUFFER
绑定,并且缓冲区对象的数据存储当前已映射,则会生成.GL_INVALID_OPERATION
如果glDrawArrays
在执行glBegin
和相应的执行之间执行,则生成glEnd
.GL_INVALID_OPERATION
将由glDrawArrays
或glDrawElements
当前程序对象中的任何两个活动采样器具有不同类型,但引用相同的纹理图像单元.GL_INVALID_OPERATION
如果几何着色器处于活动状态且模式与当前安装的程序对象中几何着色器的输入基元类型不兼容,则会生成.GL_INVALID_OPERATION
如果模式是GL_PATCHES
并且没有曲面细分控制着色器处于活动状态,则生成.GL_INVALID_OPERATION
如果将基元的顶点记录到用于变换反馈目的的缓冲区对象,则会生成超出任何缓冲区对象大小的限制,或者超出结束位置偏移+大小-1,如下所示glBindBufferRange
.GL_INVALID_OPERATION
glDrawArrays()
如果不存在几何着色器,则生成变换反馈,并且模式不是允许的模式之一.GL_INVALID_OPERATION
glDrawArrays()
如果存在几何着色器,则生成变换反馈,并且几何着色器的输出基元类型与变换反馈primitiveMode不匹配.GL_INVALID_OPERATION
如果绑定着色器程序无效,则生成.GL_INVALID_OPERATION
如果正在使用变换反馈,则生成编辑10/10/12:绑定到变换反馈绑定点的缓冲区也绑定到数组缓冲区绑定点.这是我遇到的问题,因为我绑定了缓冲区的拼写错误.虽然规范确实声明这是非法的,但在我发现的任何文档中,它都没有列在glDrawArrays下作为它可以抛出错误的原因之一.不幸的是,我找不到任何一份官方文档,其中包括超过3篇.我不得不从众多来源收集这份清单.第7点和第8点实际上来自文档glBeginTransformFeedback
,第9点似乎根本没有记录.我发现它在某个论坛帖子中提到过.但是,我仍然不认为这个列表是完整的,因为这些似乎都没有解释我得到的错误.
glBegin
并glEnd
没有提供连.layout (points) in
,并且glDrawArrays
正在调用GL_POINTS
.GL_PATCHES
任何类型的镶嵌着色器.layout (points) out …
我正在研究一些着色器,我需要改变法线.
我在几个教程中读到了变换法线的方法,你将它们与模型视图矩阵的逆的转置相乘.但我找不到为什么会这样解释,那背后的逻辑是什么?
我试图理解GLSL中的dFdx和dFdy函数.
我理解以下内容:
我不明白变化率是指什么.它是片段坐标的变化率吗?
可能是你可以在片段着色器的两个调用之间找到任意变量的变化率吗?着色器调用是否从相邻调用中"读取"变量?对于(简单)示例:
// invokation for fragment 1
float x = 1.0;
float d = dFdx(x);
// invokation for fragment next to fragment 1 along the x axis.
float x = 2.0;
float d = dFdx(x);
Run Code Online (Sandbox Code Playgroud)
d分别为-1.0和1.0?
glsl ×10
opengl ×5
shader ×3
derivative ×1
game-engine ×1
game-physics ×1
javascript ×1
opengl-es ×1
pixel-shader ×1
pyopengl ×1
webgl ×1