gl_PointCoord undeclared in fragment shader on macOS? - c++

I'm using cocos 3.17 on Xcode 11 on Mac.
These are my fragment and vertex shaders.
myShader.frag
#ifdef GL_ES
precision lowp float;
#define LOWP lowp
#else
#define LOWP
#endif
uniform sampler2D u_texture;
varying LOWP vec4 v_fragmentColor;
uniform mat4 u_rotation;
void main()
{
mat4 t1= mat4(1);
mat4 t2= mat4(1);
t1[3] = vec4(-0.5,-0.5,1,1);
t2[3] = vec4(+0.5,+0.5,1,1);
vec2 pos = (t2 * u_rotation * t1 * vec4(gl_PointCoord, 0, 1)).xy;
gl_FragColor = v_fragmentColor * texture2D(u_texture, pos);
}
myShader.vert
#ifdef GL_ES
#define LOWP lowp
#else
#define LOWP
#endif
attribute vec4 a_position;
uniform float u_pointSize;
uniform LOWP vec4 u_fragmentColor;
varying LOWP vec4 v_fragmentColor;
void main()
{
gl_Position = CC_MVPMatrix * a_position;
gl_PointSize = u_pointSize;
v_fragmentColor = u_fragmentColor;
}
When I run it as a Mac app, it gives me this error:
cocos2d:
ERROR: 0:36: Use of undeclared identifier 'gl_PointCoord'
ERROR: 0:37: Use of undeclared identifier 'pos'
someone can help me to figure out why?

After some troubles, I found the solution.
A GLSL shader that does not have a #version directive at the top is assumed to be 1.10, but I really need version 1.2. So, I need to add '#version 120\n' as a compileTimeHeader string in the initialization:
GLProgram *program = new GLProgram();
program->initWithByteArrays(myShader_vert, myShader_frag, "#version 120\n", "");
There is a mistake in the OpenGL docs which state that gl_PointCoord is a 1.1 feature, whereas in fact it was introduced in 1.2.

Related

Change texture colors using shaders

I'm trying to change texture colors inside the GLSL context - doing so before the beginning of the OpenGL pipeline is not an option.
I have tried the following approach:
Vertex Shader
attribute highp vec2 a_TexCoord;
uniform highp mat3 u_TextureMatrix;
varying highp vec2 v_TexCoord;
highp vec4 calculatePosition();
void main()
{
gl_Position = calculatePosition();
v_TexCoord = (u_TextureMatrix * vec3(a_TexCoord,1.0)).xy;
}
attribute highp vec2 a_Vertex;
uniform highp mat3 u_TransformMatrix;
uniform highp mat3 u_ProjectionMatrix;
highp vec4 calculatePosition() {
return vec4(u_ProjectionMatrix * u_TransformMatrix * vec3(a_Vertex.xy, 1.0), 1.0);
}
Fragment Shader
uniform lowp float u_Opacity;
lowp vec4 calculatePixel();
void main()
{
gl_FragColor = calculatePixel();
gl_FragColor.a *= u_Opacity;
}
varying mediump vec2 v_TexCoord;
uniform lowp vec4 u_Color;
uniform sampler2D u_Tex0;
lowp vec4 calculatePixel() {
vec4 tex = texture2D(u_Tex0, v_TexCoord);
tex.xyz -= (100.0 / 255.0);
if (tex.x < 0.0) { tex.x += 1.0; }
if (tex.y < 0.0) { tex.y += 1.0; }
if (tex.z < 0.0) { tex.z += 1.0; }
return tex * u_Color;
}
This code works EXCEPT for the cases when Interpolation is applied (GL_LINEAR_MIPMAP_LINEAR), when things start to look really bad because the filtering happens before the Fragment Shader so I don't get to change the colors PRIOR when it's reliable to do so.
I'm developing a game that has as requirement supporting really old hardware (from as early as 2008) and that's why I'm using really obsolete GLSL code (version 120 compatible).
Is there a way to change Texture colors anywhere in the pipeline BEFORE the rasterization kicks in?

GLSL Error: "Type should be float or int"

I am trying to compile a shader, and it is compiling on Intel HD on one PC, but not on AMD drivers on another PC.
Vertex Shader:
#version 330
precision mediump float;
precision lowp sampler2D;
uniform mat4 ProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 WorldViewMatrix;
in vec3 position;
in vec2 TexCoord;
out vec2 texCoord;
void main() {
texCoord = TexCoord;
gl_Position = ProjectionMatrix * ModelViewMatrix * WorldViewMatrix * vec4(position, 1);
}
Fragment Shader:
#version 330
precision mediump float;
precision lowp sampler2D;
uniform vec4 TextureHueColor;
uniform sampler2D TextureUnit;
in vec2 texCoord;
out vec4 gl_FragColor;
void main() {
gl_FragColor = texture(TextureUnit, texCoord) * TextureHueColor;
}
On AMD drivers, I am getting:
Vertex shader failed to compile with the following errors:
ERROR: 0:3: error(#228) Type should be float or int
ERROR: error(#273) 1 compilation errors. No code generated
I am a beginner, and have no idea what is wrong with this shader, to me it looks fine. Anyone spot what's wrong?
Default precision qualifiers in GLSL 3.30 cannot be applied to sampler types. Or any type other than int or float.
Also, FYI: when using desktop GLSL (as opposed to GLSL ES), the precision qualifiers accomplish nothing. They're ignored; they exist solely for compatibility with GLSL ES shaders.

Cant enable GLSL 1.40 in my Qt application

I want to porting demo project of Box2D from VS2013 in Qt. But i have one unusual problem. When i run demo project in VS i get message with info about my openGL configuration.
I replaced code on Qt and changed initialization of shaders and calls of opengl funcitons with QOpeGL wrappers.
Firstly, i change default surface format like this:
QSurfaceFormat format;
format.setVersion(3, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
But when i debug program is format of my surface stay on 3.0.
And when i try to create shaders i get error message like this:
QOpenGLShader::compile(Vertex): ERROR: 0:1: '140' : version number not supported
ERROR: 0:2: 'layout' : syntax error
*** Problematic Vertex shader source code ***
#version 140
#line 1
uniform mat4 projectionMatrix;
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec4 v_color;
layout(location = 2) in float v_size;
out vec4 f_color;
void main(void)
{
f_color = v_color;
gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);
gl_PointSize = v_size;
}
Why VS can create shaders and work with OpenGL 3.1/GLSL 1.40, but Qt doesn't do this?
Initialize of GL (m_functions - QOpenGLExtraFunctions)
void MainOpenGLWidget::initializeGL()
{
makeCurrent();
qDebug() << "OPENGL " << QSurfaceFormat::defaultFormat().majorVersion() <<
"." << QSurfaceFormat::defaultFormat().minorVersion();
m_functions.initializeOpenGLFunctions();
m_functions.glClearColor(0, 0, 0, 0);
g_camera.m_width = 1024;
g_camera.m_height = 640;
g_debugDraw.Create(&m_functions);
}
function g_debugDraw.Create(...):
void Create(QOpenGLExtraFunctions *functions)
{
const char *vs = \
"#version 140\n"
"uniform mat4 projectionMatrix;\n"
"layout(location = 0) in vec2 v_position;\n"
"layout(location = 1) in vec4 v_color;\n"
"layout(location = 2) in float v_size;\n"
"out vec4 f_color;\n"
"void main(void)\n"
"{\n"
" f_color = v_color;\n"
" gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
" gl_PointSize = v_size;\n"
"}\n";
...
m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vs);
...
m_functions = *functions;
m_functions.glGenVertexArrays(1, &m_vaoId);
m_functions.glGenBuffers(3, m_vboIds);
m_functions.glBindVertexArray(m_vaoId);
m_functions.glEnableVertexAttribArray(m_vertexAttribute);
m_functions.glEnableVertexAttribArray(m_colorAttribute);
m_functions.glEnableVertexAttribArray(m_sizeAttribute);
...
}
I get error when call m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vs);
If you really want to stick to GLSL #version 140, then replace the following lines
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec4 v_color;
layout(location = 2) in float v_size;
by
in vec2 v_position;
in vec4 v_color;
in float v_size;
Explicit attribute location is not part of GLSL until #version 330.
Be careful after that to query your shader's attribute location before enabling it in your C++ code. The shader compiler may or may not order them in the order of declaration.
const int POS_LOCATION = glGetAttribLocation(program_id, "v_position");
if(-1 != POS_LOCATION)
{
glEnableVertexAttribArray(POS_LOCATION);
...
glVertexAttribPointer(POS_LOCATION, ... );
...
}
I've found no mention of layout(location = x) in documentation of GLSL #version 140.
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.40.pdf
Not mentioned until #version 330 at page 35.
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.3.30.pdf
In your case the shader compiler error message is a little misleading. Maybe if you update you graphic card driver you'll get a better shader compiler.
I didn't took into account that GLSL for desktop is not the same that GLSL from OpenGL ES. This topic little helped me. I change all in to attribute or varying and all out to varying and also set precision on float. After change my shader was compile. Finally my shader code looks like this:
precision lowp float;
uniform mat4 projectionMatrix;
attribute vec2 v_position;
attribute vec4 v_color;
attribute float v_size;
varying vec4 f_color;
void main(void)
{
f_color = v_color;
gl_Position = projectionMatrix * vec4(v_position, 0.0, 1.0);
gl_PointSize = v_size;
}
Thank Octo for support!

cocos2d-x position issue when using setShaderProgram

I'm using the latest cocos2d-x v3.9 (JSBinding).
And here is a code (add a sprite and attach with a simple gray shader):
this.winSize = cc.director.getWinSize();
var sprite = new cc.Sprite(res.png_building_3);
sprite.setPosition(this.winSize.width / 2, this.winSize.height / 2);
var shaderProgram = new cc.GLProgram();
shaderProgram.init("GrayScaleShader.vsh", "GrayScaleShader.fsh");
shaderProgram.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
shaderProgram.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
shaderProgram.link();
shaderProgram.updateUniforms();
sprite.setShaderProgram(shaderProgram);
this.addChild(sprite);
And here is the shader vsh:
attribute vec4 a_position;
attribute vec2 a_texCoord;
#ifdef GL_ES
varying mediump vec2 v_texCoord;
#else
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;
v_texCoord = a_texCoord;
}
and fsh:
#ifdef GL_ES
precision lowp float;
#endif
varying vec2 v_texCoord;
void main(void) {
vec4 normalColor = texture2D(CC_Texture0, v_texCoord).rgba;
float grayColor = dot(normalColor.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(grayColor, grayColor, grayColor, normalColor.a);
}
This code works fine in Browser, I can see a gray sprite in the center of the screen.
But in Mac and iOS (JSBinding) the sprite is gray but the position of the sprite is in the right top of the screen (not in the center where it should be).
Not sure what is going wrong here, any advice will be appreciated, thanks :)
For some reason in browser works with:
gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;
but in native iOS you have to modify the vertex shader to:
gl_Position = CC_PMatrix * a_position;

How to give smooth edges when filling a png with color in OpenGl/GLES

this is my fragment shader
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
varying LOWP vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
void main()
{
vec4 final_color = v_color * texture2D(u_texture, v_texCoords);
if (final_color.w != 0.0){
final_color = v_color;
}
gl_FragColor = final_color;
}
It looks like your original image is anti-aliased. Try just using the color of v_color with the alpha from the texture:
gl_FragColor.xyz = v_color.xyz;
gl_FragColor.w = texture2D(u_texture, v_texCoords).w;
if (final_color.w >= 0.0){
final_color.w = clamp(final_color.w, 0.0,1.0);
final_color.xyz = v_color.xyz;
}
gl_FragColor = final_color;
I figured out I can also use this but #GuyRT's way is more efficient