www.jpct.net
jPCT  a 3d engine for Java => Support => Topic started by: AGP on December 12, 2013, 02:06:30 am

I'd like to play around with Shadertoy's shaders. To start with, I would like to use this one: https://www.shadertoy.com/view/4slGRM (https://www.shadertoy.com/view/4slGRM). From what I gather, Shadertoy only has fragment shaders (am I right?). So I wrote a skeleton of a vertex shader that looks like this:
void main(void) {
}
I know, breathtaking, right? Still, GLSLShader tells me that the fragment shader (not my brilliant vertexshader, mind you) isn't compiled. How come?
[ Wed Dec 11 23:02:13 EST 2013 ]  ERROR: Attached fragment shader is not compiled.
// Simple Water shader. (c) Victor Korsun, bitekas@gmail.com; 2012.
//
// AttributionShareAlike CC License.
#ifdef GL_ES
precision highp float;
#endif
const float PI = 3.1415926535897932;
// play with these parameters to custimize the effect
// ===================================================
//speed
const float speed = 0.2;
const float speed_x = 0.3;
const float speed_y = 0.3;
// refraction
const float emboss = 0.50;
const float intensity = 2.4;
const int steps = 8;
const float frequency = 6.0;
const int angle = 7; // better when a prime
// reflection
const float delta = 60.;
const float intence = 700.;
const float reflectionCutOff = 0.012;
const float reflectionIntence = 200000.;
// ===================================================
float time = iGlobalTime*1.3;
float col(vec2 coord)
{
float delta_theta = 2.0 * PI / float(angle);
float col = 0.0;
float theta = 0.0;
for (int i = 0; i < steps; i++)
{
vec2 adjc = coord;
theta = delta_theta*float(i);
adjc.x += cos(theta)*time*speed + time * speed_x;
adjc.y = sin(theta)*time*speed  time * speed_y;
col = col + cos( (adjc.x*cos(theta)  adjc.y*sin(theta))*frequency)*intensity;
}
return cos(col);
}
// main
void main(void)
{
vec2 p = (gl_FragCoord.xy) / iResolution.xy, c1 = p, c2 = p;
float cc1 = col(c1);
c2.x += iResolution.x/delta;
float dx = emboss*(cc1col(c2))/delta;
c2.x = p.x;
c2.y += iResolution.y/delta;
float dy = emboss*(cc1col(c2))/delta;
c1.x += dx*2.;
c1.y = (c1.y+dy*2.);
float alpha = 1.+dot(dx,dy)*intence;
float ddx = dx  reflectionCutOff;
float ddy = dy  reflectionCutOff;
if (ddx > 0. && ddy > 0.)
alpha = pow(alpha, ddx*ddy*reflectionIntence);
vec4 col = texture2D(iChannel0,c1)*(alpha);
gl_FragColor = col;
}

If the driver reports one, there should be a log output that shows the actual compilation error. Might be that your hardware/driver doesn't support something used in that shader. The syntax of GLSL is extended from version to version.

I replaced that version of jpct (the one I'd been using wasn't even 300k in size) given what you said about syntax versions, and fixed some output messages by declaring (if not filling) some variables. Now I get the following:
ERROR: 0:? : 'premature EOF' : syntax error syntax error
[ Fri Dec 13 04:57:04 BRST 2013 ]  ERROR: Attached fragment shader is not compiled.
Tangent handle not found (tangents needed: true)!
Shader compiled!
Basically, it's whining about a premature endoffile. The following is "my" revised shader code:
// Simple Water shader. (c) Victor Korsun, bitekas@gmail.com; 2012.
//
// AttributionShareAlike CC License.
uniform float iGlobalTime;
uniform vec3 iResolution;
uniform sampler2D iChannel0..3;
#ifdef GL_ES
precision highp float;
#endif
const float PI = 3.1415926535897932;
// play with these parameters to customize the effect
// ===================================================
//speed
const float speed = 0.2;
const float speed_x = 0.3;
const float speed_y = 0.3;
// refraction
const float emboss = 0.50;
const float intensity = 2.4;
const int steps = 8;
const float frequency = 6.0;
const int angle = 7; // better when a prime
// reflection
const float delta = 60.;
const float intence = 700.;
const float reflectionCutOff = 0.012;
const float reflectionIntence = 200000.;
// ===================================================
float time = iGlobalTime*1.3;
float col(vec2 coord) {
float delta_theta = 2.0 * PI / float(angle);
float col = 0.0;
float theta = 0.0;
for (int i = 0; i < steps; i++) {
vec2 adjc = coord;
theta = delta_theta*float(i);
adjc.x += cos(theta)*time*speed + time * speed_x;
adjc.y = sin(theta)*time*speed  time * speed_y;
col = col + cos( (adjc.x*cos(theta)  adjc.y*sin(theta))*frequency)*intensity;
}
return cos(col);
}
void main(void) {
vec2 p = (gl_FragCoord.xy) / iResolution.xy, c1 = p, c2 = p;
float cc1 = col(c1);
c2.x += iResolution.x/delta;
float dx = emboss*(cc1col(c2))/delta;
c2.x = p.x;
c2.y += iResolution.y/delta;
float dy = emboss*(cc1col(c2))/delta;
c1.x += dx*2.;
c1.y = (c1.y+dy*2.);
float alpha = 1.+dot(dx,dy)*intence;
float ddx = dx  reflectionCutOff;
float ddy = dy  reflectionCutOff;
if (ddx > 0. && ddy > 0.)
alpha = pow(alpha, ddx*ddy*reflectionIntence);
vec4 col = texture2D(iChannel0,c1)*(alpha);
gl_FragColor = col;
}

For me, it compiles fine when is replace this
uniform sampler2D iChannel0..3;
with this
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform sampler2D iChannel3;

I guess I should've tried that. But are you not getting an error like the following?
[ Fri Dec 13 14:19:57 EST 2013 ]  ERROR: Vertex info

(0) : error C5145: must write to gl_Position

No, but that depends on the driver. It's a reasonable error though, because your vertex shader doesn't do anything. If you want omit the vertex shader, i think you can just null it in desktop jPCT.

No, it throws a NullPointerException if I do that. And I'd like for it to work on both platforms, if possible.

OK, with the following vertex shader the fragment shader compiles with no complaints. But now all I get is a black plain. I suppose this is because I didn't assign any textures to the water plane. So now, how do I go about initializing iChannel03?
attribute vec4 tangent;
void main(void) {
gl_Position = ftransform();
}

These are texture samplers...you set them to 0, 1, 2 and 3. Similar to the colorMap and normalMap setters in the example in the wiki.

I see the line texture2D(normalMap, texCoord), which I expect is where normalMap gets initialized. But I don't know how it references any image. Put simply: is texture2D a method that returns a sampler2D image and how do I use it?

That's reading a pixel from the texture assigned to the sampler (in this case normalMap) at the given texture coordinates.

But what I don't understand is how any texture is being assigned to the sampler2d normalMap.

That's simply the texture layer in the engine. By setting <samplerName> in the shader to some value, you assign the layer on that layer. For example, if you set normalMap to 0, the texture 0 will be sampled. If you set it to 3, the texture on layer 3.

But I don't see normalMap being assigned to any integer in the shader. And, more importantly, where, then, do you add the textures to the layers?

No, not in the shader, but in the Java code. The idea is this: You create a sampler2D uniform in the shader and in the java code, you have to set it to 0, 1, 2 or 3. The textures are then added to the layer by using a TextureInfo.

Oh, that seems easy enough. I expect that you do this with setUniform(), right? Thanks a lot.