I building a simple Framework for OpenGL UI's for MonoTouch. I set up everything and also succeeded rendering 3D Models, but a simple 2D texture object fails. The texture has a size of 256x256 so it's not to large and its power of two.
Here is some rendering code( Note: I did remove the existing, and working code ):
// Render the gui objects ( flat )
Projection = Matrix4x4.Orthographic(0, WindowProperties.Width, WindowProperties.Height, 0);
View = new Matrix4x4();
GL.Disable(All.CullFace);
GL.Disable(All.DepthTest);
_Stage.RenderGui();
Stage:
public void RenderGui ()
{
Draw(this);
// Renders every child control, all of them call "DrawImage" when rendering something
}
public void DrawImage (Control caller, ITexture2D texture, PointF position, SizeF size)
{
PointF gposition = caller.GlobalPosition; // Resulting position is 0,0 in my tests
gposition.X += position.X;
gposition.Y += position.Y;
// Renders the ui model, this is done by using a existing ( and working vertex buffer )
// The shader gets some parameters ( this works too in 3d space )
_UIModel.Render(new RenderParameters() {
Model = Matrix4x4.Scale(size.Width, size.Height, 1) * Matrix4x4.Translation(gposition.X, gposition.Y, 0),
TextureParameters = new TextureParameter[] {
new TextureParameter("texture", texture)
}
});
}
The model is using a vector2 for positions, no other attributes are given to the shader.
The shader below should render the texture.
Vertex:
attribute vec2 position;
uniform mat4 modelViewMatrix;
varying mediump vec2 textureCoordinates;
void main()
{
gl_Position = modelViewMatrix * vec4(position.xy, -3.0, 1.0);
textureCoordinates = position;
}
Fragment:
varying mediump vec2 textureCoordinates;
uniform sampler2D texture;
void main()
{
gl_FragColor = texture2D(texture, textureCoordinates) + vec4(0.5, 0.5, 0.5, 0.5);
}
I found out that the drawing issue is caused by the shader. This line produces a GL_INVALID_OPERATION( It works with other shaders ):
GL.UniformMatrix4(uni.Location, 1, false, (parameters.Model * _Device.View * _Device.Projection).ToArray());
EDIT:
It turns out that the shader uniform locations changed( Yes i'm wondering about this too, because the initialization happens when the shader is completly initialized. I changed it, and now everything works.
As mentioned in the other thread the texture is wrong, but this is another issue ( OpenGL ES 2.0 / MonoTouch: Texture is colorized red )
The shader initialization with the GL.GetUniformLocation problem mentioned above:
[... Compile shaders ...]
// Attach vertex shader to program.
GL.AttachShader (_Program, vertexShader);
// Attach fragment shader to program.
GL.AttachShader (_Program, pixelShader);
// Bind attribute locations
for (int i = 0; i < _VertexAttributeList.Length; i++) {
ShaderAttribute attribute = _VertexAttributeList [i];
GL.BindAttribLocation (_Program, i, attribute.Name);
}
// Link program
if (!LinkProgram (_Program)) {
GL.DeleteShader (vertexShader);
GL.DeleteShader (pixelShader);
GL.DeleteProgram (_Program);
throw new Exception ("Shader could not be linked");
}
// Get uniform locations
for (int i = 0; i < _UniformList.Length; i++) {
ShaderUniform uniform = _UniformList [i];
uniform.Location = GL.GetUniformLocation (_Program, uniform.Name);
Console.WriteLine ("Uniform: {0} Location: {1}", uniform.Name, uniform.Location);
}
// Detach shaders
GL.DetachShader (_Program, vertexShader);
GL.DetachShader (_Program, pixelShader);
GL.DeleteShader (vertexShader);
GL.DeleteShader (pixelShader);
// Shader is initialized add it to the device
_Device.AddResource (this);
I don't know what Matrix4x4.Orthographic uses as near-far range, but if it's something simple like [-1,1], the object may just be out of the near-far-interval, since you set its z value explicitly to -3.0 in the vertex shader (and neither the scale nor the translation of the model matrix will change that). Try to use a z of 0.0 instead. Why is it -3, anyway?
EDIT: So if GL.UniformMatrix4 function throws a GL_INVALID_OPERATION, it seems you didn't retrieve the corresponding unfiorm location successfully. So the code where you do this might also help to find the issue.
Or it may also be that you call GL.UniformMatrix4 before the corresponding shader program is used. Keep in mind that uniforms can only be set once the program is active (GL.UseProgram or something similar was called with the shader program).
And by the way, you're multiplying the matrices in the wrong order, anyway (given your shader and matrix setting code). If it really works this way for other renderings, then you either were just lucky or you have some severe conceptual and mathemtical inconsistency in your matrix library.
It turns out that the shader uniforms change at a unknown time. Everything is created and initialized when i ask OpenGL ES for the uniform location, so it must be a bug in OpenGL.
Calling GL.GetUniformLocation(..) each time i set the shader uniforms solves the problem.
Related
I have a problem that I'm finding hard to find a solution to so far... I'm also new to shaders and less new to Unity, so that probably doesn't help.
I am using AR Foundation to create an application. The application uses the camera image as a background texture. Objects in view should generally be rendered normally, but depending on the color of the camera image being rendered to the background, need to be discarded. Example: the color of the pixel in the background exceeds a certain blue value, so the object in the foreground does not render that pixel.
My approach so far has been to attempt stencil testing.
I've tried altering the AR Foundation default background shader. I've managed to do basic stuff, like set color values for the fragment before it is returned, so I assumed I could use GLES3 functions like glEnable(GL_STENCIL_TEST) to enable stencil testing. This prevents rendering all together, so I assume I can't use the full GLES3 functionality.
Using HLSL stencil testing outside the GLSLPROGRAM block works fine, but I cant figure out how to selectively chose ref values based on fragment color rendered in the GLSLPROGRAM block.
Is there a way to achieve what I'm attempting here?
This is the state of the shader currently (this is basically still the default ARCameraBackground shader, uncommenting
//glEnable(GL_STENCIL_TEST);
causes errors. Uncommenting:
//Stencil
//{
// Ref 2
// Comp Always
// Pass Replace
//}
works fine and lets me fully hide or fully show objects with shaders that stencil test as well):
Shader "CustomARCoreBackground"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_CutoffThresh("CutoffValue", Float) = 0.5
}
SubShader
{
Tags
{
"Queue" = "Background"
"RenderType" = "Background"
"ForceNoShadowCasting" = "True"
}
Pass
{
Cull Off
ZTest Always
ZWrite On
Lighting Off
LOD 100
Tags
{
"LightMode" = "Always"
}
GLSLPROGRAM
#pragma only_renderers gles3
#ifdef SHADER_API_GLES3
#extension GL_OES_EGL_image_external_essl3 : require
#endif // SHADER_API_GLES3
// Device display transform is provided by the AR Foundation camera background renderer.
uniform mat4 _UnityDisplayTransform;
#ifdef VERTEX
varying vec2 textureCoord;
void main()
{
#ifdef SHADER_API_GLES3
// Transform the position from object space to clip space.
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
// Remap the texture coordinates based on the device rotation.
textureCoord = (_UnityDisplayTransform * vec4(gl_MultiTexCoord0.x, 1.0f - gl_MultiTexCoord0.y, 1.0f, 0.0f)).xy;
#endif // SHADER_API_GLES3
}
#endif // VERTEX
#ifdef FRAGMENT
varying vec2 textureCoord;
uniform samplerExternalOES _MainTex;
//added threshold variable
uniform float _CutoffThresh;
#if defined(SHADER_API_GLES3) && !defined(UNITY_COLORSPACE_GAMMA)
float GammaToLinearSpaceExact (float value)
{
if (value <= 0.04045F)
return value / 12.92F;
else if (value < 1.0F)
return pow((value + 0.055F)/1.055F, 2.4F);
else
return pow(value, 2.2F);
}
vec3 GammaToLinearSpace (vec3 sRGB)
{
// Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
return sRGB * (sRGB * (sRGB * 0.305306011F + 0.682171111F) + 0.012522878F);
// Precise version, useful for debugging, but the pow() function is too slow.
// return vec3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b));
}
#endif // SHADER_API_GLES3 && !UNITY_COLORSPACE_GAMMA
void main()
{
//glEnable(GL_STENCIL_TEST);
#ifdef SHADER_API_GLES3
vec3 result = texture(_MainTex, textureCoord).xyz;
#ifndef UNITY_COLORSPACE_GAMMA
result = GammaToLinearSpace(result);
#endif // !UNITY_COLORSPACE_GAMMA
gl_FragColor = vec4(result, 1);
gl_FragDepth = 1.0f;
#endif // SHADER_API_GLES3
}
#endif // FRAGMENT
ENDGLSL
//Stencil
//{
// Ref 2
// Comp Always
// Pass Replace
//}
}
}
FallBack Off
}```
I'm trying to shade meshes I generated with a noise heightmap using an array of textures. With a smaller texture size (e.g. 512px*512px) everything works completely fine. However, if I use larger texture for example 1024px*1024px or 2048px*2048px, my meshes usually render black. Every now and then the textures will render correctly around 5% of the time, while around 20% of the time they will seem to render correctly for the first frame and then switch to black.
This issue seems to appear no matter how long my texture array is. (a size 1 array still causes the same behavior) I also see the same issue regardless of whether the images are JPGs or PNGs. I also tried a variety of different images as texture and reproduced the same problem. I have no errors or warnings in my console.
Below are simplified versions of the relevant code which also suffer from the same issue. This just additive blends the textures, but in the full version of the code, the height of the mesh is used to determine the texture(s) to use and the degree of blending between nearby textures. My code is based off of Sebastian Lague's procedural landmass generation youtube tutorial series, which only deals with 512px*512px textures.
The code that puts the texture array and layer number into the shader:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
[CreateAssetMenu()]
public class TextureData : UpdatableData {
const int textureSize = 2048;
const TextureFormat textureFormat = TextureFormat.RGB565;
public Layer[] layers;
public void UpdateMeshHeights(Material material, float minHeight, float maxHeight) {
material.SetInt("layerCount", layers.Length);
Texture2DArray texturesArray = GenerateTextureArray(layers.Select(x => x.texture).ToArray());
material.SetTexture("baseTextures", texturesArray);
}
Texture2DArray GenerateTextureArray(Texture2D[] textures) {
Texture2DArray textureArray = new Texture2DArray(textureSize, textureSize, textures.Length, textureFormat, true);
for (int i=0; i < textures.Length; i++) {
textureArray.SetPixels(textures[i].GetPixels(), i);
}
textureArray.Apply();
return textureArray;
}
[System.Serializable]
public class Layer {
public Texture2D texture;
}
}
The shader itself:
Shader "Custom/Terrain" {
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
int layerCount;
UNITY_DECLARE_TEX2DARRAY(baseTextures);
struct Input {
float3 worldPos;
float3 worldNormal;
};
float3 triplanar(float3 worldPos, float scale, float3 blendAxes, int textureIndex) {
float3 scaledWorldPos = worldPos / scale;
float3 xProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.y, scaledWorldPos.z, textureIndex)) * blendAxes.x;
float3 yProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.z, textureIndex)) * blendAxes.y;
float3 zProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.y, textureIndex)) * blendAxes.z;
return xProjection + yProjection + zProjection;
}
void surf (Input IN, inout SurfaceOutputStandard o) {
float3 blendAxes = abs(IN.worldNormal);
blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;
for (int i = 0; i < layerCount; i++) {
float3 textureColor = triplanar(IN.worldPos, 1, blendAxes, i);
o.Albedo += textureColor;
}
}
ENDCG
}
FallBack "Diffuse"
}
Here is a screenshot of then problem in action:
I had a similar problem, so I thought I'd document this here.
Making a global reference to the Texture2DArray created within GenerateTextureArray(..) fixed this for me:
Texture2DArray textureArray;
Texture2DArray GenerateTextureArray(Texture2D[] textures) {
textureArray = new Texture2DArray(textureSize, textureSize, textures.Length, textureFormat, true);
for (int i=0; i < textures.Length; i++) {
textureArray.SetPixels(textures[i].GetPixels(), i);
}
textureArray.Apply();
return textureArray;
}
(Of course you can then remove the return value and use the reference instead)
I can only guess the reason being, but as far as I know the Apply() function moves data to the GPU. As the data is not relevant for the CPU, the garbage collector removes it, which causes problems when updating the texture. Why exactly the reference is still needed though is questionable for me.
This is a bit complicated, but it boils down to be quite a simple problem, I hope. So here is how it goes: I am using Unity to generate a map gameobject during runtime from a bsp file which has a whole bunch of vertices, faces, uvs, texture references, and so on. The meshes created come out exactly as they should be, and all the textures come out fine. There is one problem though, there are so many meshes created with so many materials leading to many draw calls making the program slow. So I searched on a way to reduce the draw calls and I found a solution. Combine all the meshes into one big mesh and create a texture atlas by combining all the textures used. Combining the meshes works fine and combining the textures comes out great as well. Then I faced the problem of uv mapping. So I found a solution from the NVidia white paper to make a custom shader which uses the tex2d function to interpolate the texel from the texture using the uv positions with their derivatives. I think this would have worked, but my meshes have really weird triangles and I think they are ruining this solution. In the images below you can see the difference when the meshes are combined from when they are separate:
Combined Meshes with Changed UVs and Custom Shader
Separate Meshes with original UVs
This is the code I am using in the shader to set the color of the model:
o.Albedo = tex2D (_MainTex, IN.uv2_BlendTex, ddx(IN.uv_MainTex), ddy(IN.uv_MainTex)).rgb;
As you can see, I have added a second UV which is the non-tiled version of the original UV. I do that by using the frac() function, but in the C# code rather than in the shader. Since the textures can be different sizes, I had to calculate the UV before getting to the shader because I have access to the texture sizes at that time.
Here is the code I used to calculate the 2 UVs:
Rect surfaceTextureRect = uvReMappers[textureIndex];
Mesh surfaceMesh = allFaces[i].mesh;
Vector2[] atlasTiledUVs = new Vector2[surfaceMesh.uv.Length];
Vector2[] atlasClampedUVs = new Vector2[surfaceMesh.uv.Length];
for (int j = 0; j < atlasClampedUVs.Length; j++)
{
Vector2 clampedUV = new Vector2((surfaceMesh.uv[j].x - Mathf.Floor(surfaceMesh.uv[j].x)), (surfaceMesh.uv[j].y - Mathf.Floor(surfaceMesh.uv[j].y)));
float atlasClampedX = (clampedUV.x * surfaceTextureRect.width) + surfaceTextureRect.x;
float atlasClampedY = (clampedUV.y * surfaceTextureRect.height) + surfaceTextureRect.y;
atlasTiledUVs[j] = new Vector2((surfaceMesh.uv[j].x * surfaceTextureRect.width) + surfaceTextureRect.x, (surfaceMesh.uv[j].y * surfaceTextureRect.height) + surfaceTextureRect.y);
atlasClampedUVs[j] = new Vector2(atlasClampedX, atlasClampedY);
if (i < 10) { Debug.Log(i + " Original: " + surfaceMesh.uv[j] + " ClampedUV: " + clampedUV); }
}
surfaceMesh.uv = atlasTiledUVs;
surfaceMesh.uv2 = atlasClampedUVs;
The array uvReMappers is an array of Rect created when using the Texture2D function PackTextures().
Sorry for taking so long, but here is my question: Why do the textures come out contorted. Is it because the way the meshes are triangulated or is it because of the way I wrote the custom shader. And finally how can I fix it.
Thank you for your time. I am sorry for writing so much, but I have never posted a question before. I always find answers to almost all my problems online, but I have been searching for days on how to fix this problem. I feel it might be too specific to be able to find an answer for. I hope I have provided enough information.
I finally solved the problem! So it turns out I should not calculate the UVs before the shader. Instead I passed the information needed by the shader through the UVs so that it can calculate the new texel positions directly.
Here is the code before the shader:
Rect surfaceTextureRect = uvReMappers[textureIndex];
Mesh surfaceMesh = allFaces[i].mesh;
Vector2[] atlasTexturePosition = new Vector2[surfaceMesh.uv.Length];
Vector2[] atlasTextureSize = new Vector2[surfaceMesh.uv.Length];
for (int j = 0; j < atlasTexturePosition.Length; j++)
{
atlasTexturePosition[j] = new Vector2(surfaceTextureRect.x, surfaceTextureRect.y);
atlasTextureSize[j] = new Vector2(surfaceTextureRect.width, surfaceTextureRect.height);
}
surfaceMesh.uv2 = atlasTexturePosition;
surfaceMesh.uv3 = atlasTextureSize;
Here is the shader code:
tex2D(_MainTex, float2((frac(IN.uv.x) * IN.uv3.x) + IN.uv2.x, (frac(IN.uv.y) * IN.uv3.y) + IN.uv2.y));
I took a different approach and created a texture atlas on the cpu, from there UV mapping was just like normal UV mapping all I had to do was assign a texture to the vertex info from my atlas ...
My scenario is a custom voxel engine that can handle anything from minecraft to rendering voxel based planets and I haven't found a scenario it can't handle yet.
Here's my code for the atlas ...
using UnityEngine;
using Voxels.Objects;
namespace Engine.MeshGeneration.Texturing
{
/// <summary>
/// Packed texture set to be used for mapping texture info on
/// dynamically generated meshes.
/// </summary>
public class TextureAtlas
{
/// <summary>
/// Texture definitions within the atlas.
/// </summary>
public TextureDef[] Textures { get; set; }
public TextureAtlas()
{
SetupTextures();
}
protected virtual void SetupTextures()
{
// default for bas atlas is a material with a single texture in the atlas
Textures = new TextureDef[]
{
new TextureDef
{
VoxelType = 0,
Faces = new[] { Face.Top, Face.Bottom, Face.Left, Face.Right, Face.Front, Face.Back },
Bounds = new[] {
new Vector2(0,1),
new Vector2(1, 1),
new Vector2(1,0),
new Vector2(0, 0)
}
}
};
}
public static TextureDef[] GenerateTextureSet(IntVector2 textureSizeInPixels, IntVector2 atlasSizeInPixels)
{
int x = atlasSizeInPixels.X / textureSizeInPixels.X;
int z = atlasSizeInPixels.Z / textureSizeInPixels.Z;
int i = 0;
var result = new TextureDef[x * z];
var uvSize = new Vector2(1f / ((float)x), 1f / ((float)z));
for (int tx = 0; tx < x; tx++)
for (int tz = 0; tz < z; tz++)
{
// for perf, types are limited to 255 (1 byte)
if(i < 255)
{
result[i] = new TextureDef
{
VoxelType = (byte)i,
Faces = new[] { Face.Top, Face.Bottom, Face.Left, Face.Right, Face.Front, Face.Back },
Bounds = new[] {
new Vector2(tx * uvSize.x, (tz + 1f) * uvSize.y),
new Vector2((tx + 1f) * uvSize.x, (tz + 1f) * uvSize.y),
new Vector2((tx + 1f) * uvSize.x, tz * uvSize.y),
new Vector2(tx * uvSize.x, tz * uvSize.y)
}
};
i++;
}
else
break;
}
return result;
}
}
}
And for a texture definition within the atlas ...
using UnityEngine;
using Voxels.Objects;
namespace Engine.MeshGeneration.Texturing
{
/// <summary>
/// Represents an area within the atlas texture
/// from which a single texture can be pulled.
/// </summary>
public class TextureDef
{
/// <summary>
/// The voxel block type to use this texture for.
/// </summary>
public byte VoxelType { get; set; }
/// <summary>
/// Faces this texture should be applied to on voxels of the above type.
/// </summary>
public Face[] Faces { get; set; }
/// <summary>
/// Atlas start ref
/// </summary>
public Vector2[] Bounds { get; set; }
}
}
For custom scenarios where I need direct control of the UV mappings I inherit texture atlas and then override the SetupTextures() method but in pretty much all cases for me I create atlases where the textures are all the same size so simply calling GenerateTextureSet will do the uv mapping calculations I believe you need.
The UV coords for a given face of a given voxel type are then ...
IEnumerable<Vector2> UVCoords(byte voxelType, Face face, TextureAtlas atlas)
{
return atlas.Textures
.Where(a => a.VoxelType == voxelType && a.Faces.Contains(face))
.First()
.Bounds;
}
In your case you probably have a different way to map to the texture of choice from your pack but essentially the combination of a face and type in my case are what determine the uv mapping set I want.
This then allows you to use your mesh with any standard shader instead of relying on custom shader logic.
You have to turn the passed in TEXCOORD0 from a percentage of the image space to a pixel value, use the modulus to figure out which pixel it is on the tiled texture, and then turn it back into a percentage of the image.
Here's the code:
You need the 2D variables _MainTex and _PatternTex to be defined.
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
float modFunction(float number, float divisor){
//2018-05-24: copied from an answer by Nicol Bolas: https://stackoverflow.com/questions/35155598/unable-to-use-in-glsl
return (number - (divisor * floor(number/divisor)));
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 curColor = tex2D(_MainTex, i.uv);
fixed4 pattern = tex2D(_PatternTex,
float2(
modFunction(i.uv.x*_MainTex_TexelSize.z,_PatternTex_TexelSize.z) *_PatternTex_TexelSize.x,
modFunction(i.uv.y*_MainTex_TexelSize.w,_PatternTex_TexelSize.w) *_PatternTex_TexelSize.y
)
);
fixed4 col = curColor * pattern;
col.rgb *= col.a;
return col;
}
I'm new to OpenGL ES 2.0 so please bear with me... I'd like to pass a BOOL flag into my fragment shader so that after a certain touch event has occurred in my app, it renders gl_FragColor differently. I tried using a vec2 attribute for this and just "faking" the .x value as my "BOOL" but it looks like OpenGL is normalizing the value from 0.0 to 1.0 before the shader gets ahold of it. So even though in my app I've set it to 0.0, while the shader is doing its thing, the value will eventually reach 1.0. Any suggestions would be hugely appreciated.
VertexAttrib Code:
// set up context, shaders, use program etc.
[filterProgram addAttribute:#"inputBrushMode"];
inputBrushModeAttribute = [filterProgram attributeIndex:#"inputBrushMode"];
bMode[0] = 0.0;
bMode[1] = 0.0;
glVertexAttribPointer(inputBrushModeAttribute, 2, GL_FLOAT, 0, 0, bMode);
Current Vertex Shader Code:
...
attribute vec2 inputBrushMode;
varying highp float brushMode;
void main()
{
gl_Position = position;
...
brushMode = inputBrushMode.x;
}
Current Fragment Shader Code:
...
varying highp float brushMode;
void main()
{
if(brushMode < 0.5) {
// render the texture
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
} else {
// cover things in yellow funk
gl_FragColor = vec4(1,1,0,1);
}
}
Thanks in advance.
Create the bool as a glUniform (1.0 or 0.0) instead. Set its value with glUniform1f(GLint location, GLfloat v0). In the shader, check its value like so:
if (my_uniform < 0.5) {
// FALSE
} else {
// TRUE
}
I'm trying to modify the fragment shader which is part of the standard iPhone/XCode OpenGL ES template. I want to make it so that every other row of pixels is transparent. I have this code so far:
varying lowp vec4 colorVarying;
void main()
{
gl_FragColor = vec4(colorVarying.x, colorVarying.y, colorVarying.z, floor(mod(gl_FragCoord.y, 2.0)));
}
But when I compile and run I still get the same square moving up and down with no other effects.
Here is my vertex shader (my keyboard just broke so no return key! DOH!)
attribute vec4 position;
attribute vec4 color;
varying vec4 colorVarying;
uniform float translate;
void main()
{
gl_Position = position;
gl_Position.y += sin(translate) / 2.0;
colorVarying = color;
}
Using this vertex shader and fragment shader above, I get no 'scanline effect' which I was hoping for. I'm testing using the iPad simulator and also the 3.1.3 iPhone simulator.
What am I doing wrong here? I'm a complete n00b at Glsl - I'm trying to teach myself the very basics (starting with this tutorial) .
Can you post your vertex shader as well? Assuming that it's passing over the vec4 colorVarying there's no reason it shouldn't work when squashed into a single line as opposed to the two-line code in the sample (posted below)
float odd = floor(mod(gl_FragCoord.y, 2.0));
gl_FragColor = vec4(colorVarying.x, colorVarying.y, colorVarying.z, odd);
The only other difference I see is that you specified lowp - try it without that.