I can't find the issue with my offset to coordinate and vice versa mapping however there's a problem that manifests itself very repeatedly as soon as the sizes get slightly large. This runs on Chrome.
I am trying a 55x56 texture and I use the following routines to map from a logical interger offset to the uv (st) of TexCoords and back. Somehere some error gets accumulated causing two subsequent offset (eg. 54 and 55) to map to the same texel.
The line for halfTexel addition below was found in one of StackOverflow posts (and it makes very much sense). At the beginning of my shader i also have this line:
// const vec2 halfTexel = vec2(${1.0 / (2.0 * xScale)}, ${1.0 / (2.0 * yScale)});
// xscale is the width (55)
// yscale is the height (56)
precision highp float;
...
vec2 offsetToCoords_A(int offset) {
const vec2 halfTexel = vec2(0.00909090909090909, 0.008928571428571428);
const float xScale = 55.0;
const float yScale = 56.0;
float offsetF = float(offset);
float s = mod(offsetF, 55.0);
float t = floor(offsetF / 55.0);
vec2 coords = vec2(s/xScale, t/yScale) + halfTexel;
return coords;
}
int coordsToOffset_A(vec2 coords) {
const float xScale = 55.0;
const float yScale = 56.0;
float s = coords.s * xScale;
float t = coords.t * yScale;
int offset = int(t) * 55 + int(s);
return offset;
}
sample result:
49,50,51,52,53,54,54,56,57,58,59,
...
106,107,108,109,109,111,112,113
Removed the mod and changed offsetToCoords to the following:
vec2 offsetToCoords_A(int offset) {
const vec2 halfTexel = vec2(0.00909090909090909, 0.008928571428571428);
const float xScale = 55.0;
const float yScale = 56.0;
int t = offset / int(xScale);
int s = offset - t*int(xScale);
vec2 coords = vec2(s,t)/vec2(xScale, yScale) + halfTexel;
return coords;
}
Related
I'm trying to render an ellipse where I can decide how hard the edge is.
(It should also be tileable, i.e. I must be able to split the rendering into multiple textures with a given offset)
I came up with this:
float inEllipseSmooth(vec2 pos, float width, float height, float smoothness, float tiling, vec2 offset)
{
pos = pos / iResolution.xy;
float smoothnessSqr = smoothness * tiling * smoothness * tiling;
vec2 center = -offset + tiling / 2.0;
pos -= center;
float x = (pos.x * pos.x + smoothnessSqr) / (width * width);
float y = (pos.y * pos.y + smoothnessSqr) / (height * height);
float result = (x + y);
return (tiling * tiling) - result;
}
See here (was updated after comment -> now it's how I needed it):
https://www.shadertoy.com/view/ssGBDK
But at the moment it is not possible to get a completely hard edge. It's also smooth if "smoothness" is set to 0.
One idea was "calculating the distance of the position to the center and comparing that to the corresponding radius", but I think there is probably a better solution.
I was not able to find anything online, maybe I'm just searching for the wrong keywords.
Any help would be appreciated.
I don't yet understand what you are trying to accomplish.
Anyway, I have been playing with shadertoy and I have created something that could help you.
I think that smoothstep GLSL function is what you need. And some inner and outer ratio to set the limits of the inner and border.
It is not optimized...
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
int tiling = 4;
float width = 0.5;
float height = 0.2;
float smoothness = 0.9;
float outerRatio = 1.0;
float innerRatio = 0.75;
vec2 offset = vec2(0.25, 0.75);
//offset = iMouse.xy / iResolution.xy;
vec2 center = vec2(0.5, 0.5);
vec2 axis = vec2(width, height);
vec2 pos = float(tiling) * (fragCoord.xy);
pos = mod(pos / iResolution.xy, 1.0);
pos = mod(pos - offset, 1.0);
pos = pos - center;
pos = (pos * pos) / (axis * axis);
float distance = pos.x + pos.y;
float alpha;
if ( distance > outerRatio ) { alpha = 0.0; }
else if ( distance < innerRatio ) { alpha = 1.0; }
else { alpha = smoothstep(outerRatio, innerRatio, distance); }
fragColor = vec4(vec3(alpha), 1.0);
}
Shadertoy multiple ellipses with soft edge and solid inner
There are two draw object groups that I'd like to combine into one canvas, a rain effect layer and points forming a circle. These are their vertex shader codes, taken from this website
// Rain effect
const vs = `#version 300 es
uniform int numVerts;
uniform float time;
// hash function from https://www.shadertoy.com/view/4djSRW
// given a value between 0 and 1
// returns a value between 0 and 1 that *appears* kind of random
float hash(float p) {
vec2 p2 = fract(vec2(p * 5.3983, p * 5.4427));
p2 += dot(p2.yx, p2.xy + vec2(21.5351, 14.3137));
return fract(p2.x * p2.y * 95.4337);
}
void main() {
float u = float(gl_VertexID) / float(numVerts); // goes from 0 to 1
float off = floor(time + u) / 1000.0; // changes once per second per vertex
float x = hash(u + off) * 2.0 - 1.0; // random position
float y = fract(time + u) * -2.0 + 1.0; // 1.0 -> -1.0
gl_Position = vec4(x, y, 0, 1);
gl_PointSize = 2.0;
}
`;
// Points forming a circle
const vs = `#version 300 es
uniform int numVerts;
uniform vec2 resolution;
#define PI radians(180.0)
void main() {
float u = float(gl_VertexID) / float(numVerts); // goes from 0 to 1
float angle = u * PI * 2.0; // goes from 0 to 2PI
float radius = 0.8;
vec2 pos = vec2(cos(angle), sin(angle)) * radius;
float aspect = resolution.y / resolution.x;
vec2 scale = vec2(aspect, 1);
gl_Position = vec4(pos * scale, 0, 1);
gl_PointSize = 5.0;
}
`;
Both shaders assign different values to gl_Position and gl_PointSize. I couldn't think of a way to combine them under one vertex shader without conflict. It doesn't help that the vertex dataset is entirely generated on site, inside the shader instead of having it passed from the buffer.
Add a uniform variable to the shader that indicates which algorithm to use.
#version 300 es
uniform int numVerts;
uniform float time;
uniform int mode; // 0 or 1
// hash function
// [...]
void main() {
float u = float(gl_VertexID) / float(numVerts); // goes from 0 to 1
vec2 pos;
float pointSize;
if (mode == 0) {
float off = floor(time + u) / 1000.0; // changes once per second per vertex
float x = hash(u + off) * 2.0 - 1.0; // random position
float y = fract(time + u) * -2.0 + 1.0; // 1.0 -> -1.0
pos = vec2(x, y);
pointSize = 2.0
}
else {
float angle = u * PI * 2.0; // goes from 0 to 2PI
float radius = 0.8;
float aspect = resolution.y / resolution.x;
vec2 scale = vec2(aspect, 1);
pos = vec2(cos(angle), sin(angle)) * radius * scale;
pointSize = 5.0;
}
gl_Position = vec4(pos, 0, 1);
gl_PointSize = pointSize;
}
I seem to be getting boxy perlin noise terrain on 2d input.
I have been following this https://www.shadertoy.com/view/4tGSzW, which uses WebGL instead of opengl. Where i have replaced the gradient method of taking from some sample texture by a float array of range 0.0 to 1.0.
#version 330 core
out vec4 FragColor;
uniform float gradient[256];
float fade(float t)
{
return t*t*t*(t*(t*6.0-15.0)+10.0);
}
vec2 grad(vec2 p){
vec2 v = vec2(gradient[int(p.x)&255],gradient[int(p.y)&255]);
return normalize(v.xy*2.0 - vec2(1.0));
}
float noise(vec2 p){
vec2 p0 = floor(p);
vec2 p1 = p0 + vec2(1.0,0.0);
vec2 p2 = p0 + vec2(0.0,1.0);
vec2 p3 = p0 + vec2(1.0,1.0);
vec2 g0 = grad(p0);
vec2 g1 = grad(p1);
vec2 g2 = grad(p2);
vec2 g3 = grad(p3);
float t0 = p.x - p0.x;
float fade_t0 = fade(t0);
float t1 = p.y - p0.y;
float fade_t1 = fade(t1);
float p0p1 = (1.0-fade_t0)*dot(g0,(p-p0)) + fade_t0*dot(g1,(p-p1));
float p2p3 = (1.0-fade_t0)*dot(g2,(p-p2)) + fade_t0*dot(g3,(p-p3));
return ((1.0-fade_t1)*p0p1 + fade_t1*p2p3);
}
void main()
{
float n = noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/64.0)*1.0 +
noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/32.0) * 0.5 +
noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/16.0) * 0.25 +
noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/8.0) * 0.125;
FragColor = vec4(vec3(n*0.5+0.5),1.0);
}
Boxy perlin noise Image being generated
The source texture in the shadertoy version is 2 dimensional and consists of 256*256 random pixels and multiple color channels.
Further when the texture is looked up in the original grad function then the pixels are interpolated according to the texture minification filter, which is probably GL_LINEAR.
vec2 grad(vec2 p) {
const float texture_width = 256.0;
vec4 v = texture(iChannel0, vec2(p.x / texture_width, p.y / texture_width));
return normalize(v.xy*2.0 - vec2(1.0));
}
Your uniform array has just 256 different values and the interpolation between the texels is not emulated in your grad function:
vec2 grad(vec2 p){
vec2 v = vec2(gradient[int(p.x)&255],gradient[int(p.y)&255]);
return normalize(v.xy*2.0 - vec2(1.0));
}
Use a Random noise functions and interpret the return value of the noise function as an angle (noise*2*PI) to calculate the return value of grad():
float rand(vec2 co){
return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
}
vec2 grad(vec2 p){
float a = rand(p) * 2.0 * 3.1415926;
return vec2(cos(a), sin(a));
}
Or use the uniform array to generate a random value
vec2 grad(vec2 p){
ivec2 i00 = ivec2(int(p.x)&255, int(p.y)&255);
vec2 f = floor(p);
float vx = mix(gradient[i00.x], gradient[i00.x+1], f.x);
float vy = mix(gradient[i00.y], gradient[i00.y+1], f.y);
float a = (vx + vy) * 3.141529;
return vec2(cos(a), sin(a));
}
I encounter some difficulties to implement a procedural texture of checkerboard. Here is what I need to get:
Here is what i get:
It's close but my texture is kind of rotated in respect of what I need to get.
Here is the code of my shader:
#version 330
in vec2 uv;
out vec3 color;
uniform sampler1D colormap;
void main() {
float sx = sin(10*3.14*uv.x)/2 + 0.5;
float sy = sin(10*3.14*uv.y)/2 + 0.5;
float s = (sx + sy)/2;
if(true){
color = texture(colormap,s).rgb;
}
colormap is a mapping from 0 to 1, where 0 correspond to red, 1 to green.
I think the problem is coming from the formula i use, (sx+sy)/2 . I need to get the square not rotated but aligned with the border of the big square.
If someone has an idea to get the good formula.
Thanks.
You can add a rotation operation to "uv":
mat2 R(float degrees){
mat2 R = mat2(1);
float alpha = radians(degrees);
R[0][0] = cos(alpha);
R[0][1] = sin(alpha);
R[1][0] = -sin(alpha);
R[1][1] = cos(alpha);
return R;
}
void main(){
ver2 new_uv = R(45) * uv;
float sx = sin(10*3.14*new_uv.x)/2 + 0.5;
float sy = sin(10*3.14*new_uv.y)/2 + 0.5;
float s = (sx + sy)/2;
color = texture(colormap,s).rgb;
}
Maybe something like this:
float sx = sin(10.0 * M_PI * uv.x);
float sy = sin(10.0 * M_PI * uv.y);
float s = sx * sy / 2.0 + 0.5;
Example (without texture):
https://www.shadertoy.com/view/4sdSzn
I have a volume rendering program write by OpenGL and GLSL.Now I need calculate a fragment's depth value .The follow code is my fragment shader program
#version 120
//
some needed variable declaration
//
float calculateDepthValue(float t, float entryPointsDepth, float exitPointsDepth)
{
// assign front value given in windows coordinates
float zw_front = entryPointsDepth;
// and convert it into eye coordinates
float ze_front = 1.0 / ((zw_front - const_to_z_e_1)*const_to_z_e_2);
// assign back value given in windows coordinates
float zw_back = exitPointsDepth;
// and convert it into eye coordinates
float ze_back = 1.0 / ((zw_back - const_to_z_e_1)*const_to_z_e_2);
// interpolate in eye coordinates
float ze_current = ze_front + t*(ze_back - ze_front);
// convert back to window coordinates
float zw_current = (1.0 / ze_current)*const_to_z_w_1 + const_to_z_w_2;
return zw_current;
}
float getDepthValue(float t, float tEnd, float entryPointsDepth, float exitPointsDepth)
{
if (t >= 0.0)
return calculateDepthValue(t / tEnd, entryPointsDepth, exitPointsDepth);
else
return 1.0;
}
vec4 compositeDVR(in vec4 curResult, in vec4 color,in float t, in float pvar,inout float tDepth)
{
vec4 result = curResult;
// apply opacity correction to accomodate for variable sampling intervals
color.a = 1.0 - pow(1.0 - color.a, pvar);
result.rgb = result.rgb + (1.0 - result.a) * color.a * color.rgb;
result.a = result.a + (1.0 - result.a) * color.a;
// save first hit ray parameter for depth value calculation
if (tDepth < 0.0)
tDepth = t;
return result;
}
void main()
{
vec2 p = gl_FragCoord.xy * screenDimRCP_;
vec3 start = texture2D(frontTex, p).rgb;
vec3 end = texture2D(texBack, p).rgb;
float entryDepth = texture2D(entryPointsDepth_, p).z;
float exitDepth = texture2D(exitPointsDepth_, p).z;
//
some needed code
//
lookup = texture1D(globalTex, sample);
if (lookup.a > 0.0)
{
lookup.rgb = phongShading(N, texToPhysicalPos, position_, cPos, lookup.rgb, lookup.rgb, vec3(1.0, 1.0, 1.0));
//compositeDVR
result = compositeDVR(result, lookup, t, powAlp, tDepth);
}
gl_FragDepth = getDepthValue(tDepth, tEnd, entryDepth, exitDepth);
gl_FragColor = result;
}
In fragment shader,some function come from Voreen's code.my program's result is that gl_FragDepth all equal 1,this is wrong.any people can help me?