gpt4 book ai didi

opengl - 统一点数组和管理片段着色器坐标系

转载 作者:行者123 更新时间:2023-12-02 09:01:22 30 4
gpt4 key购买 nike

我的目标是将点数组传递给着色器,计算它们到片段的距离,并用一个圆圈绘制它们,该圆圈的颜色取决于该计算的渐变。

例如:
enter image description here
(来自working example I set up on shader toy)

不幸的是,我不清楚应该如何计算和转换传递给着色器内部处理的坐标。

我目前正在尝试的是将两个 float 组(一个用于每个点的 x 位置,一个用于 y 位置)通过统一传递给着色器。然后在着色器内部迭代每个点,如下所示:

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

uniform float sourceX[100];
uniform float sourceY[100];
uniform vec2 resolution;

in vec4 gl_FragCoord;

varying vec4 vertColor;
varying vec2 center;
varying vec2 pos;

void main()
{
float intensity = 0.0;

for(int i=0; i<100; i++)
{
vec2 source = vec2(sourceX[i],sourceY[i]);
vec2 position = ( gl_FragCoord.xy / resolution.xy );
float d = distance(position, source);
intensity += exp(-0.5*d*d);
}

intensity=3.0*pow(intensity,0.02);

if (intensity<=1.0)
gl_FragColor=vec4(0.0,intensity*0.5,0.0,1.0);
else if (intensity<=2.0)
gl_FragColor=vec4(intensity-1.0, 0.5+(intensity-1.0)*0.5,0.0,1.0);
else
gl_FragColor=vec4(1.0,3.0-intensity,0.0,1.0);
}

但这不起作用 - 我相信这可能是因为我试图使用像素坐标而没有正确翻译它们。谁能向我解释一下如何进行这项工作?

更新:

当前结果是: current result草图的代码是:

PShader pointShader;

float[] sourceX;
float[] sourceY;


void setup()
{

size(1024, 1024, P3D);
background(255);

sourceX = new float[100];
sourceY = new float[100];
for (int i = 0; i<100; i++)
{
sourceX[i] = random(0, 1023);
sourceY[i] = random(0, 1023);
}


pointShader = loadShader("pointfrag.glsl", "pointvert.glsl");
shader(pointShader, POINTS);
pointShader.set("sourceX", sourceX);
pointShader.set("sourceY", sourceY);
pointShader.set("resolution", float(width), float(height));
}


void draw()
{
for (int i = 0; i<100; i++) {
strokeWeight(60);
point(sourceX[i], sourceY[i]);
}
}

而顶点着色器是:

#define PROCESSING_POINT_SHADER

uniform mat4 projection;
uniform mat4 transform;


attribute vec4 vertex;
attribute vec4 color;
attribute vec2 offset;

varying vec4 vertColor;
varying vec2 center;
varying vec2 pos;

void main() {

vec4 clip = transform * vertex;
gl_Position = clip + projection * vec4(offset, 0, 0);

vertColor = color;
center = clip.xy;
pos = offset;
}

最佳答案

更新:

根据评论,您似乎混淆了两种不同的方法:

  1. 绘制单个全屏多边形,传入点并使用着色器中的循环计算每个片段一次的最终值。
  2. 为每个点绘制边界几何体,在片段着色器中计算一个点的密度,并使用加法混合对所有点的密度求和。

另一个问题是您的点以像素为单位给出,但代码期望范围为 0 到 1,因此 d很大并且点是黑色的。将此问题修复为 @RetoKoradi describes应该解决黑色点的问题,但我怀疑当许多点非常接近时,您会发现斜坡剪切问题。将点传递到着色器会限制可扩展性,并且效率低下,除非这些点覆盖整个视口(viewport)。

如下所示,我认为坚持方法 2 更好。要为其重构代码,请删除循环,不要传入点数组并使用 center作为点坐标:

//calc center in pixel coordinates
vec2 centerPixels = (center * 0.5 + 0.5) * resolution.xy;

//find the distance in pixels (avoiding aspect ratio issues)
float dPixels = distance(gl_FragCoord.xy, centerPixels);

//scale down to the 0 to 1 range
float d = dPixels / resolution.y;

//write out the intensity
gl_FragColor = vec4(exp(-0.5*d*d));

Draw this to a texture (来自评论: opengl-tutorial.org codethis question )与添加剂 blending :

glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);

现在该纹理将包含 intensity就像在原来的循环之后一样。在全屏 channel 期间的另一个片段着色器中(绘制覆盖整个视口(viewport)的单个三角形),继续:

uniform sampler2D intensityTex;
...
float intensity = texture2D(intensityTex, gl_FragCoord.xy/resolution.xy).r;
intensity = 3.0*pow(intensity, 0.02);
...
<小时/>

您显示的代码很好,假设您正在绘制一个全屏多边形,因此片段着色器为每个像素运行一次。潜在的问题是:

  • resolution设置不正确
  • 点坐标不在屏幕上的 0 到 1 范围内。
  • 虽然很小,d将按纵横比拉伸(stretch),因此您可能最好将点缩放到像素坐标和潜水距离 resolution.y .

这看起来与创建 2D 密度场非常相似 metaballs 。为了提高性能,您最好限制每个点的密度函数,这样它就不会永远持续下去,然后使用加法混合将圆盘喷射到纹理中。这可以节省对点不影响的像素的处理(就像延迟着色一样)。结果是密度场,或者在您的情况下为每像素 intensity .

这些有点相关:

关于opengl - 统一点数组和管理片段着色器坐标系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31141429/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com