Heello,大家好! 我一直在尝试编写一个使用GLSL渲染Mandelbrot集的脚本,但是发生了一些奇怪的事情。
我将效果函数称为:
vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords){
但是,当我尝试使用texture_coords值时,比如说:
vec2 c = vec2((texture_coords[0]-WD/2)/100, (texture_coords[1]-HT/2)/100);
它为每个像素返回相同的值;另一方面,如果我使用screen_coords,它可以工作,但是我很担心如果我拖动窗口可能会对结果产生影响。
为什么我无法检索texture_coords?
更深入了解该计划和问题here
更新
我已经重做了代码,现在它看起来像这样:
vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 window_coords)
{
vec2 c = vec2( ( MinRe + window_coords[0] * ( MaxRe - MinRe ) / ( width + 1 ) ),
( MaxIm - window_coords[1] * ( MaxIm - MinIm ) / ( height + 1 ) )
);
vec2 z = c;
vec2 zn = vec2(0.0, 0.0);
int n_iter = 0;
while( (z[0]*z[0] + z[1]*z[1] < 4) && (n_iter < max_iter)) {
zn[0] = z[0]*z[0] - z[1]*z[1] + c[0];
zn[1] = 2* z[0]*z[1] + c[1];
z[0] = zn[0];
z[1] = zn[1];
n_iter++;
}
哪个效果很好。但是当我使用texture_coords而不是window_coords时,代码会向每个像素返回相同的值,尽管我使用的纹理与窗口的大小相同。
答案 0 :(得分:1)
问题是如果不加载图像,love.graphics
的某些可绘制对象不会设置任何纹理坐标。因此,您应该使用draw.rectangle
:
Mesh
用于绘制任意纹理形状的2D多边形网格
为了添加网格对象,您可以添加到加载函数:
function love.load()
width, height = love.graphics.getDimensions( )
local vertices = {
{
-- top-left corner
0, 0, -- position of the vertex
0, 0, -- texture coordinate at the vertex position
255, 0, 0, -- color of the vertex
},
{
-- top-right corner
width, 0,
1, 0, -- texture coordinates are in the range of [0, 1]
0, 255, 0
},
{
-- bottom-right corner
width, height,
1, 1,
0, 0, 255
},
{
-- bottom-left corner
0, height,
0, 1,
255, 255, 0
},
}
-- the Mesh DrawMode "fan" works well for 4-vertex Meshes.
mesh = love.graphics.newMesh(vertices, "fan")
-- ... other stuff here ...
end
并在绘图功能中:
function love.draw()
-- ...
love.graphics.draw(mesh,0,0)
-- ...
end
完整的代码,考虑到您之前的问题和我对此的回答,添加一些行来管理坐标转换:
function love.load()
width, height = love.graphics.getDimensions( )
local vertices = {
{
-- top-left corner
0, 0, -- position of the vertex
0, 0, -- texture coordinate at the vertex position
255, 0, 0, -- color of the vertex
},
{
-- top-right corner
width, 0,
1, 0, -- texture coordinates are in the range of [0, 1]
0, 255, 0
},
{
-- bottom-right corner
width, height,
1, 1,
0, 0, 255
},
{
-- bottom-left corner
0, height,
0, 1,
255, 255, 0
},
}
mesh = love.graphics.newMesh(vertices, "fan")
GLSLShader = love.graphics.newShader[[
vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
extern int max_iter;
extern vec2 size;
extern vec2 left_top;
vec4 clr(int n){
if(n == max_iter){return black;}
float m = float(n)/float(max_iter);
float r = float(mod(n,256))/32;
float g = float(128 - mod(n+64,127))/255;
float b = float(127 + mod(n,64))/255;
if (r > 1.0) {r = 1.0;}
else{
if(r<0){r = 0;}
}
if (g > 1.0) {g = 1.0;}
else{
if(g<0){g = 0;}
}
if (b > 1.0) {b = 1.0;}
else{
if(b<0){b = 0;}
}
return vec4(r, g, b, 1.0);
}
vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 window_coords){
vec2 c = vec2(texture_coords[0]*size[0] + left_top[0],texture_coords[1]*size[1] - left_top[1]);
vec2 z = vec2(0.0,0.0);
vec2 zn = vec2(0.0,0.0);
int n_iter = 0;
while ( (z[0]*z[0] + z[1]*z[1] < 4) && (n_iter < max_iter) ) {
zn[0] = z[0]*z[0] - z[1]*z[1] + c[0];
zn[1] = 2*z[0]*z[1] + c[1];
z[0] = zn[0];
z[1] = zn[1];
n_iter++;
}
return clr(n_iter);
}
]]
end
function love.draw()
center_x = -0.5
center_y = 0.0
size_x = 3
size_y = size_x*height/width
GLSLShader:send("left_top",{center_x-size_x*0.5,center_y+size_y*0.5})
GLSLShader:send("size",{size_x,size_y})
GLSLShader:sendInt("max_iter",1024)
love.graphics.setShader(GLSLShader)
love.graphics.draw(mesh,0,0)
love.graphics.setShader()
end
答案 1 :(得分:0)
但它有点误导,因为我的纹理是窗口的大小,而且它不起作用
好吧,让我们调查一下。你并没有完全提供很多信息,但无论如何我们都要看。
(texture_coords[0]-WD/2)/100
那是什么?好吧,我们知道texture_coords
是什么。来自Love2D维基:
纹理内部的位置以获取像素数据。纹理坐标通常标准化为(0,0)到(1,1)的范围,左上角为(0,0)。
因此,您从此纹理坐标WD/2
中减去。你没有提到WD
值是什么。但无论如何,你将结果除以100。
那么,究竟是什么WD
?让我们看看代数是否可以提供帮助:
val = (texture_coords[0]-WD/2)/100
val * 100 = texture_coords[0] - WD / 2
(val * 100) - texture_coords[0] = -WD / 2
-2 * ((val * 100) - texture_coords[0]) = WD
那么,WD
是什么?那么,从这个等式,我可以确定......没有。这个等式似乎是胡言乱语。
我猜你打算让WD
表示“宽度”(严重的是,它是三个以上的字符;你不能输出那个?)。据推测,纹理的宽度。如果是这样......等式仍然是乱码。
您正在取一个范围为[0,1]的值,然后从中减去纹理宽度的一半。那是什么意思?为什么除以100?由于纹理宽度可能远大于texture_coords
(aka:1)中的最大值,因此结果基本上是-WD/200
。
除非你渲染到浮点图像,否则它将被限制在有效的颜色范围内:[0,1]。所以你的所有价值都是相同的颜色:黑色。
由于你在谈论Mandelbrot等等,我怀疑你正在尝试在[-1,1]或其他任何范围内生成值。如果texture_coords
在范围[0,1]上不是标准化纹理坐标,那么你的等式可能会这样做。你知道,就像Wiki所说的那样。
如果你想将纹理坐标转换为[-1,1]范围,它实际上要简单得多。这就是我们使用规范化纹理坐标的原因:
vec2 c = (2 * texture_coord) - 1; //Vector math is good.
如果你希望它是[-100,100]范围,只需将结果乘以100.