我想知道在较新的着色器模型中是否支持从目标帧缓冲区读回像素值.我认为这在绘图管道的后期(非可编程)阶段是完成的,这使我希望这个特性可能已被添加到可编程管道中.
我知道可以绘制到纹理绑定的帧缓冲区,然后将此纹理发送到着色器,我只是希望有一种更优雅的方式来实现相同的功能.
我正在尝试将Shadertoy转换为Javascript和WebGL,以便它可以独立于Shadertoy运行.Shadertoy具有缓冲区的概念,在此示例中,它重新循环缓冲区并改善输出图像.它在Buf A选项卡上执行此操作.
https://www.shadertoy.com/view/MdyGDW
它通过将其输出写入与iChannel0绑定的缓冲区A然后在每个绘制周期从同一iChannel0读取来完成此操作.如何在WebGL Javascript片段着色器中实现缓冲区的概念,WebGL使用GLSL语言.特别是在这种情况下,它能够写入缓冲区,然后在下一个渲染周期从同一缓冲区读取.
我有另一个OpenGL ES驱动程序错误.这次我正在尝试编译以下行:
precision mediump float;
varying highp vec2 textureCoordinate;
void main() {
highp vec4 color = texture2D(input0, textureCoordinate);
vec3 color3 = color.rgb;
vec2 tc = (2.0 * textureCoordinate) - 1.0;
float d = dot(tc, tc);
vec2 lookup = vec2(d, color3.r);
..
..
}
Run Code Online (Sandbox Code Playgroud)
但是我正在接受这条线:
GLES20.glLinkProgram(program);
Run Code Online (Sandbox Code Playgroud)
本机崩溃:"致命信号11(SIGDEV)在0x00000060(代码= 1),线程1231"我猜它发生是因为LG nexus 4使用GPU Adreno,它也在我崩溃,错误代码14在另一个崩溃 - 使用太多宏.
有关如何在GLSL着色器中实现有效积分函数(如SumX和SumY)的建议吗?
SumX(u)=关于x = I(u0,y)+ I(u1,y)+ ... + I(uN,y)的积分; u =归一化x坐标SumY(v)=关于y = I(x,v0)+ I(x,v1)+ ... + I(x,vN)的积分; v =标准化的y坐标
例如,第一行的第5个像素将是第一行上所有五个像素的总和.并且最后一个像素将是所有先前像素的总和,包括最后一个像素本身.
我希望在一个着色器中组合两个纹理,就像您对 Photoshop 之类的程序所期望的那样。也就是说,一种纹理叠加在另一种纹理之上,就好像分层一样。两个纹理都将具有 Alpha,并且结果输出也应具有正确的组合 Alpha。
然而,尽管用谷歌搜索公式,我无法得到正确的颜色。使用此处的参考:(https://microsoft.github.io/Win2D/html/PremultipliedAlpha.htm)例如产生;
(注意灰色 50% 叠加的差异)
着色器代码在 libgdx 中设置以使用它作为混合;
context.setBlending(true,GL20.GL_SRC_ALPHA ,GL20.GL_ONE_MINUS_SRC_ALPHA);
Run Code Online (Sandbox Code Playgroud)
我相当确定错误出在我的片段着色器混合中(请参见上图中的代码),因为如果我将输入纹理 (A) 直接传递给 gl_FragColor,那么我会得到 A 的像素完美颜色匹配,包括其 alpha。
例如;
gl_FragColor = 反向漫反射;
工作正常。
=====
编辑
根据建议,我尝试使用预乘阿尔法代替。
context.setBlending(true,GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
Run Code Online (Sandbox Code Playgroud)
然而,即使着色器刚刚设置为输出 A,这也会产生错误的效果
backdiffuse = texture2D(u_backSample2D, vTexCoord);
backdiffuse=backdiffuse*backdiffuse.a; //convert to premultiply
gl_FragColor = backdiffuse;
Run Code Online (Sandbox Code Playgroud)
我是否将 libgdxs 混合设置错误?这显然太亮了。
解决方案(感谢接受的答案);
backdiffuse.rgb *= backdiffuse.a; //premultiply source
v_backBackColor.rgb *= v_backBackColor.a; //premultiply source
finalCol.rgb = backdiffuse.rgb + (v_backBackColor.rgb * (1 - backdiffuse.a));
finalCol.a = backdiffuse.a + (v_backBackColor.a * (1.0 - …Run Code Online (Sandbox Code Playgroud) GLSL 给出这样的错误:
无法从“highp float”转换为“highp float 3分量向量”
T选择了错误部分:
vec3 bRgb = texture2D(u_img1, vUv).rgb;
vec3 aRgb = texture2D(u_aImg, vUv).rgb;
vec3 target1 = aRgb * bRgb;
vec3 alum = dot( aRgb, w );
vec3 blum = dot( bRgb, w );
vec3 clum = dot( target1, w );
vec3 target2 = (alum + blum) / (2. * clum); // This is the error line
gl_FragColor = vec4(target2, 1.);
Run Code Online (Sandbox Code Playgroud)
我可以找到错误行,但我不知道如何让它运行。
我对 SpriteKit 中着色器的概念和使用非常陌生。
我发现本教程介绍了如何使用附加到 Color Sprite 的自定义着色器属性的自定义着色器文件 - Fractal.fsh 渲染 Mandelbrot 分形。
https://www.weheartswift.com/fractals-Xcode-6/
它工作得很好,我认为学习 OpenGL ES 和 SpriteKit 中的自定义着色器将是一个有趣的练习。
不过,根据 Apple 的说法,OpenGL ES 自 iOS 12 起已被弃用。
我的问题是这样的:
这是否意味着 SpriteKit 中使用的自定义着色器现在应该用 Metal 编写?
我试图弄清楚如何在 Metal 中重写第一个链接中提到的 fractal.fsh 着色器代码,但我还没有找到任何有关如何将现有自定义 SKShader 从 OpenGL ES 转换为 Metal 的资源。然而,我并不是在寻找有人重写该代码以使用 Metal,而只是寻找一个指向正确方向的指针。
更新: 根据@Knight0fDragon 的回答,我将尝试澄清我的问题:
SKShader 类的文档指出:
“SKShader 对象包含自定义 OpenGL ES 片段着色器。”
https://developer.apple.com/documentation/spritekit/skshader
那么,如果 SKShader 对象拥有自定义的 OpenGL ES 片段着色器,那么在对 OpenGL ES 的支持被弃用后,它将拥有什么?
如果从 iOS 12 开始无法使用 OpenGL ES,那么如何继续创建一个在 SpriteKit 中使用的自定义片段着色器呢?首先,我认为包含 GLSL 代码的 *.fsh 文件可以替换为包含等效金属代码的 *.metal …
Let's consider this mcve:
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import textwrap
from string import Template
def compile(shader_type, source):
identifier = glCreateShader(shader_type)
glShaderSource(identifier, source)
glCompileShader(identifier)
if not glGetShaderiv(identifier, GL_COMPILE_STATUS):
for i, l in enumerate(source.splitlines()):
print(f"{i+1}: {l}")
raise Exception(glGetShaderInfoLog(identifier).decode("utf-8"))
return identifier
def create_program(vs, fs):
vs_identifier = compile(GL_VERTEX_SHADER, vs)
fs_identifier = compile(GL_FRAGMENT_SHADER, fs)
program = glCreateProgram()
glAttachShader(program, vs_identifier)
glAttachShader(program, fs_identifier)
glLinkProgram(program)
if not glGetProgramiv(program, GL_LINK_STATUS):
raise RuntimeError(glGetProgramInfoLog(program))
return program
def set_uniform1f(prog, name, v0):
# print("set_uniform1f", name, …Run Code Online (Sandbox Code Playgroud) 这是我第一次处理使用 Angular 构建的项目,因此我仍在习惯针对 Angular 和 WebPack 的大量实践。
我希望在全屏画布中加载自定义片段着色器(.frag/.glsl)以用作组件的背景。对于过去的模型或其他不使用角度的项目,我设法在GlslCanvas等库的帮助下轻松做到这一点,这些库管理全屏四边形和基本制服的设置,但现在我无法弄清楚向我抛出的一些错误当尝试构建我的角度应用程序时。
经过几个小时的浏览,我找到了如何成功导入着色器代码,使用GLSL-shader-loader并通过 @Angular-devkit/build-Angular 和 @Angular-builder/custom-webpacks 添加自定义 Webpack 配置:
# my-custom-webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.(frag|vert|glsl)$/,
use: [
{
loader: 'glsl-shader-loader',
options: {}
}
]
}]
}
}
Run Code Online (Sandbox Code Playgroud)
我还了解到我必须通过定义所需的声明来阻止打字稿抱怨导入时的非 ts 模块,即:
# my-declarations.d.ts
declare module '*.glsl';
declare module '*.frag';
declare module '*.vert';
Run Code Online (Sandbox Code Playgroud)
此时,片段着色器的代码已正确导入(或者我认为是这样?),我可以将其记录或打印出来(例如{{ myShaderCode }}):
# glsl-bg.component.ts
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import frag from './myShader.frag';
import * as GlslCanvas …Run Code Online (Sandbox Code Playgroud) 我试图让我的着色器在 Shaderfrog 中工作,我通过 URL 导入我的 glsl 沙箱版本。
我收到错误:“C:\fakepath(111,2-27):警告 X3550:数组引用不能用作左值;本身不可寻址,强制循环展开。
真的不确定为什么会发生这个错误,我尝试取消循环内的任何循环,但无济于事。
这是我的片段代码:
#extension GL_OES_standard_derivatives : enable
precision highp float;
varying vec2 vUv;
uniform float time;
uniform vec2 resolution;
void main()
{
vec2 p = vUv.xy / resolution.x * .05;
vec3 col;
for (float j = 0.; j < 3.; j++) {
p.x += ((0.05 / 2.0) * sin(2.0 * 10. * p.y + (time*0.2) + cos((time / (150. * 2.0)) * 2.0)));
p.y += ((0.02 / 2.0)* cos(2.0 * 10. * …Run Code Online (Sandbox Code Playgroud)