Convert a shader to OpenGL 2.x? - macos

I have some OpenGL 2.x code on which I want to run these shaders:
static const char* YUYV_VS = ""
"#version 150\n"
"uniform mat4 u_pm;"
"uniform mat4 u_mm;"
"in vec4 a_pos;"
"in vec2 a_tex;"
"out vec2 v_tex;"
"void main() {"
" gl_Position = u_pm * u_mm * a_pos; "
" v_tex = a_tex;"
"}"
"";
static const char* YUYV_FS = ""
"#version 150\n"
"uniform sampler2D u_tex;"
"out vec4 outcol;"
"in vec2 v_tex;"
"const vec3 R_cf = vec3(1.164383, 0.000000, 1.596027);"
"const vec3 G_cf = vec3(1.164383, -0.391762, -0.812968);"
"const vec3 B_cf = vec3(1.164383, 2.017232, 0.000000);"
"const vec3 offset = vec3(-0.0625, -0.5, -0.5);"
"void main() {"
" vec3 tc = texture( u_tex, v_tex ).rgb;"
" vec3 yuv = vec3(tc.g, tc.b, tc.r);"
" yuv += offset;"
" outcol.r = dot(yuv, R_cf);"
" outcol.g = dot(yuv, G_cf);"
" outcol.b = dot(yuv, B_cf);"
" outcol.a = 1.0;"
"}"
"";
Trouble is, OpenGL 2.x doesn't support shaders of version 150. Does anyone have an idea how I would back-convert the shaders to 2.x?

Use this procedure except start at GLSL 1.50 spec instead of the 1.30 one.

File shader.vsh
uniform mat4 u_pm;
uniform mat4 u_mm;
attribute vec4 a_pos;
attribute vec2 v_tex;
varying vec2 fragmentTextureCoordinates;
void main() {
gl_Position = u_pm * u_mm * a_pos;
fragmentTextureCoordinates = v_tex;
}
File shader.fsh
uniform sampler2D u_tex;
varying vec2 fragmentTextureCoordinates;
const vec3 R_cf = vec3(1.164383, 0.000000, 1.596027);
const vec3 G_cf = vec3(1.164383, -0.391762, -0.812968);
const vec3 B_cf = vec3(1.164383, 2.017232, 0.000000);
const vec3 offset = vec3(-0.0625, -0.5, -0.5);
void main() {
vec3 tc = texture2D(u_tex, fragmentTextureCoordinates).rgb;
vec3 yuv = vec3(tc.g, tc.b, tc.r);
yuv += offset;
gl_FragColor.r = dot(yuv, R_cf);
gl_FragColor.g = dot(yuv, G_cf);
gl_FragColor.b = dot(yuv, B_cf);
gl_FragColor.a = 1.0;
}
Would that work? You may have to adapt the variables you pass to your program/technique/shaders.

Related

shader and cook-torrance cannot output texture

I am completely new to opengl es shader and cook-torrance,
the following shader only output red, no texture color processed for ambient light and point light.
the cube is for testing,no shader applied to it, the right side rocket with texture with no output,just red color. Any opengl es guy can help?
no texture only red
original texture before apply cook-torrance and output by gl_FragColor =texture2D(texture,vertTexCoord.st).rgb*vertColor;
But what make CookTorance() below fail?
fragment shader
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PI 3.14159265
//copper
uniform vec3 diffuseColor = vec3(0.75164,0.60648,0.22648);
uniform vec3 specularColor = vec3(0.256777,0.137622,0.086014);
uniform float F0 = 0.8;
uniform float roughness = 0.1;
uniform float k = 0.2;
//uniform vec3 lightColor = vec3(1, 1, 1);
uniform sampler2D texture;
varying vec4 varyvertColor;
varying vec3 ecNormal; //eye normal
varying vec3 lightDir;
varying vec4 varyambient;
varying vec4 varyspecular;
varying float varyshininess; //0.1
varying vec4 vertTexCoord;
varying vec4 vposition;
vec3 CookTorrance(vec3 materialDiffuseColor,
vec3 materialSpecularColor,
vec3 normal,
vec3 lightDir,
vec3 viewDir,
vec3 lightColor)
{
float NdotL = max(0, dot(normal, lightDir));
float Rs = 0.0;
if (NdotL > 0)
{
vec3 H = normalize(lightDir + viewDir);
float NdotH = max(0, dot(normal, H));
float NdotV = max(0, dot(normal, viewDir));
float VdotH = max(0, dot(lightDir, H));
// Fresnel reflectance
float F = pow(1.0 - VdotH, 5.0);
F *= (1.0 - F0);
F += F0;
// Microfacet distribution by Beckmann
float m_squared = roughness * roughness;
float r1 = 1.0 / (4.0 * m_squared * pow(NdotH, 4.0));
float r2 = (NdotH * NdotH - 1.0) / (m_squared * NdotH * NdotH);
float D = r1 * exp(r2);
// Geometric shadowing
float two_NdotH = 2.0 * NdotH;
float g1 = (two_NdotH * NdotV) / VdotH;
float g2 = (two_NdotH * NdotL) / VdotH;
float G = min(1.0, min(g1, g2));
Rs = (F * D * G) / (PI * NdotL * NdotV);
}
return materialDiffuseColor * lightColor * NdotL + lightColor * materialSpecularColor * NdotL * (k + Rs * (1.0 - k));
}
void main(){
vec3 direction = normalize(lightDir);
//vec3 normal = normalize(ecNormal);
vec3 normal = -normalize(ecNormal);
vec4 vertColor = varyambient +
vec4(CookTorrance(texture2D(texture,vertTexCoord.st).rgb*varyvertColor.xyz,
varyspecular.xyz*specularColor,
vposition.xyz,
direction,
normal,
varyvertColor.rgb),1.0);
gl_FragColor = vertColor;
}
is there any error in the above cook-torrance?
please help on it.
the vertex shader
uniform mat4 modelviewMatrix;
uniform mat4 transformMatrix;
uniform mat3 normalMatrix;
uniform mat4 texMatrix;
attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
attribute vec4 ambient;
attribute vec4 specular;
attribute float shininess;
attribute vec2 texCoord;
varying vec4 vposition;
varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;
varying vec4 varyambient;
varying vec4 varyspecular;
varying float varyshininess;
varying vec4 varyvertColor;
varying vec4 vertTexCoord;
void main() {
// Vertex in clip coordinates
gl_Position = transformMatrix * position;
vposition = transformMatrix * position;
// Vertex in eye coordinates
vec3 ecVertex = vec3(modelviewMatrix * position);
// Normal vector in eye coordinates
ecNormal = normalize(normalMatrix * normal);
varyambient=ambient;
varyspecular=specular;
varyshininess=shininess;
varyvertColor=color;
vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}

How to make visible uniform variable in both shaders?

I have variable in vertex shader "uIsTeapot".
uniform float uIsTeapot;
Vertex shader work with it very well, but fragment shader don't see it. If I use
if (uIsTeapot == 0.0)
then an error occured
"uIsTeapot": undeclared identifier
but I defined it in vertex shader. If I define uIsTeapot in both shaders as uniform, then program say "Could not initialise shaders" since program don't pass veryfication
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
EDITED:
I add mediump to variables and now program compiled without errors, but result is one object on screen, but I draw two object.
Vertex shader
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
uniform vec3 uAmbientColor;
uniform vec3 uPointLightingLocation;
uniform vec3 uPointLightingColor;
uniform mediump float uIsTeapot;
//varying float vIsTeapot;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
varying vec4 vColor;
void main(void) {
if (uIsTeapot == 1.0) {
vec4 mvPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
gl_Position = uPMatrix * mvPosition;
vec3 lightDirection = normalize(uPointLightingLocation - mvPosition.xyz);
vec3 transformedNormal = uNMatrix * aVertexNormal;
float directionalLightWeighting = max(dot(transformedNormal, lightDirection), 0.0);
directionalLightWeighting = 100.0;
vLightWeighting = uAmbientColor + uPointLightingColor * directionalLightWeighting;
vTextureCoord = aTextureCoord;
}
if (uIsTeapot == 0.0) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
} }
Fragment shader
precision mediump float;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
varying vec4 vColor;
uniform sampler2D uSampler;
uniform mediump float uIsTeapot;
//varying float vIsTeapot;
void main(void) {
if (uIsTeapot == 1.0) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
} else {
gl_FragColor = vColor;
}
}
You need to declare it in both shaders, with the same precision.
What do you mean by:
then program don't work right.
Can you post your vertex shader and your fragment shader? I suspect you are relying on the default precision, and it is likely that you are using highp in the vertex shader and mediump in the fragment shader
Try using:
uniform mediump float uIsTeapot;
... in both vertex shader and fragment shader.

Vertex and Fragment shaders for lighting effect in OpenGL ES20

I want to add a very simply lighting effect in my models via shaders. I found out there a vertex and a fragment shaders that make the work on OpenGL:
static const char* vertSource = {
"uniform vec3 lightPosition;\n"
"varying vec3 normal, eyeVec, lightDir;\n"
"void main()\n"
"{\n"
" vec4 vertexInEye = gl_ModelViewMatrix * gl_Vertex;\n"
" eyeVec = -vertexInEye.xyz;\n"
" lightDir = vec3(lightPosition - vertexInEye.xyz);\n"
" normal = gl_NormalMatrix * gl_Normal;\n"
" gl_Position = ftransform();\n"
"}\n"
};
static const char* fragSource = {
"uniform vec4 lightDiffuse;\n"
"uniform vec4 lightSpecular;\n"
"uniform float shininess;\n"
"varying vec3 normal, eyeVec, lightDir;\n"
"void main (void)\n"
"{\n"
" vec4 finalColor = gl_FrontLightModelProduct.sceneColor;\n"
" vec3 N = normalize(normal);\n"
" vec3 L = normalize(lightDir);\n"
" float lambert = dot(N,L);\n"
" if (lambert > 0.0)\n"
" {\n"
" finalColor += lightDiffuse * lambert;\n"
" vec3 E = normalize(eyeVec);\n"
" vec3 R = reflect(-L, N);\n"
" float specular = pow(max(dot(R, E), 0.0), shininess);\n"
" finalColor += lightSpecular * specular;\n"
" }\n"
" gl_FragColor = finalColor;\n"
"}\n"
};
The problem is that I am working in OpenGL ES2, because I am developing an Android app. And it seems that the in-built variable gl_FrontLightModelProduct is not available for GLES20, because I am having compilation fails in this line.
My question therefore is: How I can modify the above shaders to make them work in a OpenGL ES20 context?
gl_FrontLightModelProduct.sceneColor gives the Ambient colour of the scene which can be 0 if you want the area which is not affected by light to be fully black. You can replace that with a vec4(0.0, 0.0, 0.0, 1.0);
You should also remove these variables and send them as uniforms.
gl_ModelViewMatrix (send as uniform)
gl_Vertex (read this from attributes)
gl_NormalMatrix (send as uniform)
gl_Normal (read this from attributes)
Or instead of fighting in converting OpenGL shader, you can search for Simple OpenGL ES 2.0 shaders

texture atlas tiling

i'm trying simple texture splatting on ios opengl es 2.0 (ipad). I have 4 tiled textures in pvrt compressed atlas (2x2 tiles). 4 single textures on 4 texture units was terribly slow.
vertex shader:
attribute lowp vec4 position;
attribute lowp vec2 tex0;
varying lowp vec2 surfCoord;
uniform mat4 projection_modelview;
uniform lowp float uv_coef;
varying lowp vec2 texCoord1;
varying lowp vec2 texCoord2;
varying lowp vec2 texCoord3;
varying lowp vec2 texCoord4;
void main()
{
gl_Position = projection_modelview * position;
vec2 texCoord = fract(vec2(position.x / uv_coef, position.y / uv_coef));
texCoord1 = texCoord * 0.5;
texCoord2 = texCoord1 + vec2(0.5, 0);
texCoord3 = texCoord1 + vec2(0, 0.5);
texCoord4 = texCoord1 + vec2(0.5, 0.5);
surfCoord = tex0;
}
fragment shader:
uniform sampler2D texture0; // surface alpha map
uniform sampler2D texture1; // atlas
varying lowp vec2 surfCoord;
varying lowp vec2 texCoord1;
varying lowp vec2 texCoord2;
varying lowp vec2 texCoord3;
varying lowp vec2 texCoord4;
void main()
{
lowp vec4 surfTexel = texture2D(texture0, surfCoord);
lowp vec4 texel1 = texture2D(texture1, texCoord1);
lowp vec4 texel2 = texture2D(texture1, texCoord2);
lowp vec4 texel3 = texture2D(texture1, texCoord3);
lowp vec4 texel4 = texture2D(texture1, texCoord4);
texel1 *= surfTexel.r;
texel2 = mix(texel1, texel2, surfTexel.g);
texel3 = mix(texel2, texel3, surfTexel.b);
gl_FragColor = mix(texel3, texel4, surfTexel.a);
}
shows this one:
(source: inputwish.com)
My problem is probably texture unit interpolators but i don't how to resolve. I don't see mistake in my shaders. Any advice please?
mistake is using fract in vertex shader. it's too early. It should be in fragment shader:
lowp vec4 texel1 = texture2D(texture1, fract(texCoord) * 0.5);
lowp vec4 texel2 = texture2D(texture1, fract(texCoord) * 0.5 + vec2(0.5, 0.0));
lowp vec4 texel3 = texture2D(texture1, fract(texCoord) * 0.5 + vec2(0.0, 0.5));
lowp vec4 texel4 = texture2D(texture1, fract(texCoord) * 0.5 + vec2(0.5, 0.5));
... and mix them together..
anyway it's slow because dependent texture reads on ipad ios.

GLSL bypassing float array to uniform

setShaders
muOffsetHandle = getUniformLocation("offset");
muWeightHandle = getUniformLocation("weight");
useProgram
GLES20.glUniform1fv(muOffsetHandle, 1, mOffset, 0);
GLES20.glUniform1fv(muWeightHandle, 1, mWeight, 0);
vars
private int muOffsetHandle;
private int muWeightHandle;
protected float mOffset[] =new float[] {0.0f, 1.3f, 3.3f};
protected float mWeight[] =new float[] {0.2f, 0.3f, 0.3f};
FragmentShader
"uniform float offset[3];\n" +
"uniform float weight[3];\n" +
then trying to reach: weight[i]
I get this:
Shader log: 0:13: S0004: Member reference or swizzle attempted on non-structure and non-vector
line 13: tc += texture2D(uFrameBufferTexture, vTextureCoord[0].xy + vec2(0.0, offset[i])/uScreenHeight).rgb * weight[i];
(i = 0 to 2)
so my question: How to bypassing a float array to a uniform? float[3]
the code
protected static final String mFShader =
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform float uTime;\n" +
"uniform float uScreenWidth;\n" +
"uniform float uScreenHeight;\n" +
"uniform sampler2D uFrameBufferTexture;\n"+
"uniform float offset[3];\n" +
"uniform float weight[3];\n" +
"void main() {\n"+
" vec3 tc = vec3(1.0, 0.0, 0.0);\n"+
" if (vTextureCoord[0].x<(uTime-0.01)) {\n"+
" tc = texture2D(uFrameBufferTexture, vTextureCoord[0].xy).rgb * weight[0];\n"+
" for (int i=1; i<3; i++) {\n"+
" tc += texture2D(uFrameBufferTexture, vTextureCoord[0].xy + vec2(0.0, offset[i])/uScreenHeight).rgb * weight[i];\n"+
" tc += texture2D(uFrameBufferTexture, vTextureCoord[0].xy - vec2(0.0, offset[i])/uScreenHeight).rgb * weight[i];\n"+
" }\n"+
" }\n"+
" else if (vTextureCoord[0].x>=(uTime+0.01)) {\n"+
" tc = texture2D(uFrameBufferTexture, vTextureCoord[0].xy).rgb;\n"+
" }\n"+
" gl_FragColor = vec4(tc, 1.0);\n"+
"}\n";
The problem isn't actually with weight or offset. The compiler is complaining that you say vTextureCoord[0].xy, but you declared vTextureCoord as varying vec2 vTextureCoord;.
Either declare vTextureCoord as an array, or don't say [0].
You don't need to declare it as an array, but if you want you can simply use:
varying vec4 vTextureCoord[3]; // you can use anything you want between the brackets
Also, don't forget to modify the varying the the vertex shader too so that they will be identical.

Resources