Tag: glsl

WebGL / GLSL – ShaderToy如何工作?

最近,我一直在围绕着Shadertoy – https://www.shadertoy.com/ ,努力学习更多关于OpenGL和GLSL的知识。 从我目前所了解的情况来看,OpenGL用户首先必须准备好要使用的所有几何graphics,并configurationOpenGL服务器(光源数量,纹理存储等)。 一旦完成,用户必须在OpenGL程序编译之前至less提供一个顶点着色器程序和一个片段着色器程序。 但是,当我查看Shadertoy上的代码示例时,我只能看到一个着色器程序,并且大部分使用的几何graphics似乎直接写入GLSL代码。 这是如何运作的? 我的猜测是顶点着色器已经预先准备好了,可编辑/采样着色器只是一个片段着色器。 但是这并不能解释一些更复杂的例子中的几何。 任何人都可以解释Shadertoy是如何工作的?

为什么有一个单独的投影matrix,然而结合模型和视图matrix是有好处的?

当你在学习3D编程时,你会被教导最简单的3个变换matrix: 模型matrix 。 这个matrix是每个单独的模型的个体,它旋转和按比例缩放对象,最终将其移动到3D世界中的最终位置。 “模型matrix将模型坐标转换为世界坐标”。 查看matrix 。 这个matrix对于大量的对象通常是相同的(如果不是全部),它将根据当前的“摄像头位置”旋转和移动所有的对象。 如果您想要使用相机拍摄3D场景,并且屏幕上显示的是由本相机拍摄的图像,则相机的位置及其观看方向将定义场景的哪些部分是可见的以及对象出现在捕获的图像上。 在渲染一个单独的帧的时候改变视图matrix的理由很less,但实际上存在(例如,通过渲染场景两次,改变视图matrix,你可以在场景中创build一个非常简单但令人印象深刻的镜像) 。 通常情况下,视图matrix在绘制的两个帧之间只改变一次。 “查看matrix将世界坐标转换为眼坐标”。 投影matrix 。 投影matrix决定如何将这些3D坐标映射到2D坐标,例如,如果有一个应用于它们的视angular(物体越远离观察者越小)或不正确(正交投影)。 投影matrix几乎不会改变。 但是,只有当新的窗口大小/屏幕分辨率具有与以前不同的显示宽高比时,如果要渲染到窗口中并且窗口大小已更改,或者如果您正在渲染全屏并且分辨率已更改,则可能必须更改。 有一些疯狂的效果,你可能想要改变这个matrix,但在大多数情况下,它对你的程序的整个生活非常稳定。 “投影matrix将眼坐标转换为屏幕坐标”。 这对我来说很有意义。 当然,总是可以将所有三个matrix合并成一个matrix,因为先乘以matrixA然后乘以matrixB与将matrixC乘以向量相同,其中C = B * A 现在,如果你看看经典的OpenGL(OpenGL 1.x / 2.x),OpenGL知道投影matrix。 然而,OpenGL不提供模型或视图matrix,它只提供了一个组合的模型视图matrix。 为什么? 这种devise迫使你永久地保存和恢复“视图matrix”,因为它将被应用于它的模型转换“消灭”。 为什么没有三个单独的matrix? 如果您查看新的OpenGL版本(OpenGL 3.x / 4.x),并且不使用经典的渲染pipe线,而是使用着色器(GLSL)自定义所有内容,则不再需要matrix,您必须定义你自己的matrix。 大多数人仍然保留投影matrix和模型视图matrix的旧概念。 为什么要这么做? 为什么不使用三个matrix,这意味着您不必永久保存和恢复模型视图matrix,或者使用单个组合的模型 – 视图 – 投影(MVP)matrix,这可以节省您在顶点着色器中的matrix乘法为所有渲染的单个顶点(毕竟这样的乘法不是免费的)。 所以总结一下我的问题:哪一个优点有一个组合的模型 – 视图matrix和一个单独的投影matrix,而不是有三个独立的matrix或单个MVPmatrix?

如何提高自定义OpenGL ES 2.0深度纹理生成的性能?

我有一个开源的iOS应用程序,它使用自定义的OpenGL ES 2.0着色器来显示分子结构的三维表示。 它通过使用在矩形上绘制的程序生成的球体和圆柱体冒名顶替,而不是使用大量顶点构build的这些相同的形状。 这种方法的缺点是这些冒充者对象的每个片段的深度值需要在片段着色器中计算,以便在对象重叠时使用。 不幸的是,OpenGL ES 2.0 不会让你写入gl_FragDepth ,所以我需要输出这些值到一个自定义的深度纹理。 我使用framebuffer对象(FBO)对场景进行遍历,只渲染与深度值对应的颜色,并将结果存储到纹理中。 然后这个纹理加载到我的渲染过程的后半部分,在那里生成实际的屏幕图像。 如果该阶段的某个片段处于屏幕上该点的深度纹理中存储的深度级别,则会显示该片段。 如果不是,就扔掉。 有关过程的更多信息,包括图表,可以在我的文章中find 。 这种深度纹理的产生是我渲染过程中的一个瓶颈,我正在寻找一种使其更快的方法。 它似乎比应该慢,但我不明白为什么。 为了实现这种深度纹理的正确生成,禁用GL_DEPTH_TEST ,使用glBlendFunc(GL_ONE, GL_ONE)启用glBlendEquation() ,并将glBlendEquation()设置为GL_MIN_EXT 。 我知道以这种方式输出的场景并不是像iOS设备中的PowerVR系列那样基于瓦片的延迟渲染器上最快的,但我想不出一个更好的方法来做到这一点。 我的深度片段着色器(最常见的显示元素)看起来是这个瓶颈的核心(仪器中的渲染器利用率固定在99%,表明我受限于片段处理)。 目前看起来如下所示: precision mediump float; varying mediump vec2 impostorSpaceCoordinate; varying mediump float normalizedDepth; varying mediump float adjustedSphereRadius; const vec3 stepValues = vec3(2.0, 1.0, 0.0); const float scaleDownFactor = 1.0 / 255.0; […]

什么会导致glDrawArrays产生一个GL_INVALID_OPERATION错误?

我一直在试图编写一个Marching Cubesalgorithm的双通道GPU实现,类似于使用OpenGL和GLSL的第一章GPU Gems 3。 然而,在我的第一遍调用glDrawArrays一贯失败,并有一个GL_INVALID_OPERATION 。 我查阅了所有可以find的文档,并发现了glDrawArrays可以抛出这个错误的条件: 如果非零缓冲区对象名称绑定到启用的数组或绑定到GL_DRAW_INDIRECT_BUFFER绑定并且当前映射缓冲区对象的数据存储区,则会生成GL_INVALID_OPERATION 。 如果在执行glBegin和相应的glEnd之间执行glDrawArrays则会生成GL_INVALID_OPERATION 。 如果当前程序对象中的任何两个活动采样器都是不同types的,则将由glDrawArrays或glDrawElements生成GL_INVALID_OPERATION ,但是指向相同的纹理图像单元。 如果几何着色器处于活动状态并且模式与当前安装的程序对象中的几何着色器的input基元types不兼容,则会生成GL_INVALID_OPERATION 。 如果模式是GL_PATCHES并且没有镶嵌控制着色器处于活动状态,则会生成GL_INVALID_OPERATION 。 如果将基元的顶点logging到用于变换反馈目的的缓冲区对象,则会产生GL_INVALID_OPERATION ,这会导致超出任何缓冲区对象的大小限制,或者超出由glBindBufferRange设置的结束位置offset + size – 1。 GL_INVALID_OPERATION由glDrawArrays()生成,如果不存在几何着色器,转换反馈处于活动状态,模式不是允许的模式之一。 GL_INVALID_OPERATION由glDrawArrays()生成,如果存在几何着色器,则变换反馈处于活动状态,几何着色器的输出基元types与变换反馈基元模式不匹配。 如果绑定的着色器程序无效,则会生成GL_INVALID_OPERATION 。 编辑10/10/12:如果正在使用变换反馈,并且绑定到变换反馈绑定点的缓冲区也绑定到数组缓冲区绑定点,则会生成GL_INVALID_OPERATION 。 这是我遇到的问题,由于我绑定了哪个缓冲区的拼写错误。 虽然规范声明这是非法的,但在我发现的任何文档中,glDrawArrays都没有列出它作为抛出错误的原因之一。 不幸的是,没有一个官方文档可以find涵盖3个以上的官方文档。 我不得不从很多来源收集这个清单。 第7和第8点实际上来自glBeginTransformFeedback的文档,第9点似乎没有logging。 我发现它在某个论坛post中提到。 不过,我还是不认为这个清单是完整的,因为这些清单似乎都不能解释我得到的错误。 我在任何地方都没有在程序中映射任何缓冲区。 我正在使用核心configuration文件,所以glBegin和glEnd甚至不可用。 我有两个采样器,他们是不同的types,但他们肯定映射到不同的纹理。 几何着色器是活动的,但是它的input布局是layout (points) in , glDrawArrays是用GL_POINTS调用的。 我没有使用任何types的GL_PATCHES或镶嵌着色器。 我确定我正在分配几何着色器可能输出的最大空间量。 然后我尝试了四倍。 没有帮助。 有一个几何着色器。 看下一点。 正在使用变换反馈,并且有一个几何着色器,但是输出布局是layout (points) out , glBeginTransformFeedback是用GL_POINTS调用的。 […]

在OpenGL ES 2.0 / GLSL中,您需要哪些精度说明符?

你正在填充值的variables是否指示你正在使用什么精度,在等号的右边? 例如,这里的精度说明符有什么不同之处: gl_FragColor = lowp vec4(1); 这是另一个例子: lowp float floaty = 1. * 2.; floaty = lowp 1. * lowp 2.; 如果你拿一些浮点数,并从它们中创build一个向量或matrix,那么这个向量或者matrix是否会把你填充的值的精度,或者将这些值转换成另一个精度级别? 我认为优化这个问题最能回答这个问题: dot(gl_LightSource[0].position.xyz, gl_NormalMatrix * gl_Normal) 我的意思是,如果你想要尽可能快,还是有些没用,它是否需要走这么远呢? lowp dot(lowp gl_LightSource[0].position.xyz, lowp gl_NormalMatrix * lowp gl_Normal) 我知道你可以定义float的默认精度,而且这个假设可以用于向量和之后的matrix。 为了教育的目的,我们之前已经定义了这一点: precision highp float;

为什么我的OpenGL Phong着色器performance得像一个平坦的着色器?

过去几周我一直在学习OpenGL,而且在实现Phong着色器时遇到了一些麻烦。 尽pipe我使用了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 […]

正确的方法来删除GLSL着色器?

我的代码以这种方式接近GLSL着色器pipe理,它创build每个着色器和相关程序,并删除每个着色器和程序。 我最近读了http://www.opengl.org/wiki/GLSL_Object ,那里说: 由于被附加到程序对象,着色器对象将继续存在,即使删除了着色器对象。 只有当系统不再附加到任何程序对象(当然用户要求删除它)时,它才会被系统删除。 如果我在链接到程序后在着色器对象上调用glDeleteShader() ,我只需要跟踪该程序,我可以正确地得到这个结果吗? 假设这总是正确的,是否安全?

GLSL / C ++:制服arrays?

我想离开OpenGL的灯光,做我自己的。 我希望我的着色器允许可变数量的灯光。 我们可以在GLSL着色器中声明一系列的制服吗? 如果是的话,我们如何设定这些制服的价值呢?

将值列表传递给片段着色器

我想发送一个值列表到片段着色器。 这是一个可能很大(几千项长)的单精度浮标清单。 片段着色器需要随机访问这个列表,我想在每一帧刷新CPU的值。 我正在考虑如何做到这一点的选项: 作为数组types的统一variables(“uniform float x [10];”)。 但是这里似乎是有限制的,在我的GPU上发送超过几百个数值是非常慢的,而且当我想要在运行时改变它时,我也必须对着色器中的上限进行硬编码。 作为具有高度1和我的列表宽度的纹理,然后使用glCopyTexSubImage2D刷新数据。 其他方法? 我最近并没有跟上GL规范的所有变化,或许还有其他一些专门为此目的而devise的方法?

内部映射着色器自我阴影

我正在修改Joost van Dongen的内部映射着色器 ,我试图实现自我阴影。 我仍然无法弄清楚阴影投射光vector所需要的坐标。您可以在这里看到有些工作演示,我已经将光位置与相机位置的偏移连接起来,以查看发生了什么,但是显然它没有看起来也不错。 着色器代码如下。 在片段着色器中查找SHADOWS DEV。 有问题的vector是: shad_E和shad_I 。 顶点着色器: varying vec3 oP; // surface position in object space varying vec3 oE; // position of the eye in object space varying vec3 oI; // incident ray direction in object space varying vec3 shad_E; // shadow light position varying vec3 shad_I; // shadow direction […]