所以我需要的是简单:每次我们执行着色器(意味着每个像素)时,我需要计算1
s和0
s的随机矩阵resolution == originalImageResolution
。怎么办这样的事情?
至于现在我已经为shadertoy创建了一个随机矩阵分辨率,这里设置为15乘15,因为当我尝试像200到200这样的东西时,gpu会使铬掉落,而我真的需要完整的图像分辨率
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 resolution;
uniform float time;
uniform sampler2D tex0;
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (43758.5453+ time));
}
vec3 getOne(){
vec2 p = gl_FragCoord.xy / resolution.xy;
vec3 one;
for(int i=0;i<15;i++){
for(int j=0;j<15;j++){
if(rand(p)<=0.5)
one = (one.xyz + texture2D(tex0,vec2(j,i)).xyz)/2.0;
}
}
return one;
}
void main(void)
{
gl_FragColor = vec4(getOne(),1.0);
}
一个用于Adobe像素弯曲器:
<languageVersion: 1.0;>
kernel random
< namespace : "Random";
vendor : "Kabumbus";
version : 3;
description : "not as random as needed, not as fast as needed"; >
{
input image4 src;
output float4 outputColor;
float rand(float2 co, float2 co2){
return fract(sin(dot(co.xy ,float2(12.9898,78.233))) * (43758.5453 + (co2.x + co2.y )));
}
float4 getOne(){
float4 one;
float2 r = outCoord();
for(int i=0;i<200;i++){
for(int j=0;j<200;j++){
if(rand(r, float2(i,j))>=1.0)
one = (one + sampleLinear(src,float2(j,i)))/2.0;
}
}
return one;
}
void
evaluatePixel()
{
float4 oc = getOne();
outputColor = oc;
}
}
所以我真正的问题是 - 我的着色器使我的GPU失败了。如何将GLSL用于我现在所做的相同目的但是如果失败并且如果可能更快?
更新 我想要创建的是Single-Pixel Camera(谷歌压缩成像或压缩感知),我想创建基于gpu的软件实现。
想法很简单:
NxM
。NxM
随机值矩阵 - 0
s和1
s。1
矩阵中NxM
s的坐标我试图在着色器中实现的是模拟那个谨慎的过程。
尝试在gpu上执行此操作真是愚蠢:
NxM
矩阵,它只是它的和平(例如1/3
)。所以我在GPU上施加了一些我不需要的压力。然而,测试更多数据并不总是一个坏主意。答案 0 :(得分:2)
感谢您添加更多详细信息以澄清您的问题。我的评论太长了,所以我要回答。将评论移到这里以使它们保持在一起:
抱歉要慢,但我想了解问题和目标。在你的GLSL样本中,我没有看到生成矩阵。我看到通过对来自15×15纹理(矩阵)的细胞的随机选择(随时间变化)求和来生成单个vec3。并且为每个像素重新计算vec3。然后将vec3用作像素颜色。
所以我不清楚你是否真的想要创建一个矩阵,或者只是想为每个像素计算一个值。后者在某种意义上是一个“矩阵”,但计算一个200 x 200像素的简单随机值不会对你的图形驱动程序造成压力。你还说要使用矩阵。所以我认为这不是你的意思。
我试图理解为什么你想要一个矩阵 - 为所有像素保持一致的随机基础?如果是这样,您可以预先计算随机纹理,或者使用与rand()中一致的伪随机函数,除非不使用时间。你清楚地知道这一点,所以我想我仍然不明白目标。为什么要为每个像素求和纹理中随机选择的单元格?
我相信你的着色器崩溃的原因是你的main()
函数超出了它的时间限制 - 对于单个像素或整个像素集。每个像素调用rand()
40,000次(在200 * 200嵌套循环中)当然可以解释这一点!
如果您有200 x 200像素,并且每个调用sin()40k次,则每帧160,000,000次调用。糟糕的GPU!
我希望如果我们更好地理解目标,我们将能够推荐一种更有效的方法来获得你想要的效果。
<强>更新强>
(删除了这一部分,因为它是错误的。即使源矩阵中的许多细胞可能各自对结果的贡献小于视觉上可检测的颜色量,但是许多细胞的总数可以提供视觉上可检测的颜色量。 。)
基于更新问题的新更新。
好的,(在这里大声思考,这样你就可以检查我是否正确理解......)因为你只需要每个随机NxM值一次,所以没有实际要求将它们存储在一个矩阵中;这些值可以简单地按需计算,然后扔掉。这就是为什么上面的示例代码实际上不会生成矩阵。
这意味着我们无法摆脱每帧生成(NxM)^ 2个随机值,即每个像素的NxM随机值,并且存在NxM个像素。因此,对于N = M = 200,每帧有1.6亿个随机值。
然而,我们仍然可以优化一些东西。
int LFSR_Rand_Gen(in int n)
{
// <<, ^ and & require GL_EXT_gpu_shader4.
n = (n << 13) ^ n;
return (n * (n*n*15731+789221) + 1376312589) & 0x7fffffff;
}
/2.0
)执行一个除法运算,这可能相对昂贵,除非编译器和GPU能够将其优化为位移(可能是浮点数) ?)。这也不会给出输入值的算术平均值,如上所述......它将更加重视后面的值,而对前面的值则很少。作为一个解决方案,保持计算包含的值的数量,并在循环结束后除以该计数一次。这些优化是否足以使您的GPU驱动程序能够每帧驱动200x200 * 200x200像素,我不知道。它们绝对可以让您大幅提高分辨率。
这些是我头脑中发生的想法。我不是一名GPU专家。如果有资格的人可以提出建议,那就太好了。
P.S。在你的评论中,你开玩笑地(?)提到了预先计算N * M NxM随机矩阵的选项。也许这不是一个坏主意? 40,000x40,000是一个很大的纹理(至少40MB),但如果你每个单元存储32位随机数据,那么它可以达到1250 x 40,000个单元。太糟糕的vanilla GLSL无法帮助您使用按位运算符来提取数据,但即使您没有GL_EXT_gpu_shader4扩展名,您仍然可以伪造它。 (也许你还需要一个特殊的扩展然后非方形纹理?)