Do GLSL code snippets stored in named strings have to be compileable code to #include via ARB_shading_language_include extension? - opengl

I learned how to use https://registry.khronos.org/OpenGL/extensions/ARB/ARB_shading_language_include.txt extension thanks to opengl - How to Using the #include in glsl support ARB_shading_language_include - Stack Overflow. I prepared the following named string and shader:
option A
// NamedString /lib/VertexData.glsl
struct VertexData {
vec3 objectPosition;
vec3 worldPosition;
};
VertexData fillVertexData() {
VertexData v;
v.objectPosition = objectPosition;
v.worldPosition = vec3(worldFromObject * vec4(objectPosition, 1));
return v
}
// MyShader.vert
#version 430
#extension GL_ARB_shading_language_include : require
layout(location = 0) in vec3 objectPosition;
uniform mat4 worldFromObject; // Model
uniform mat4 viewFromWorld; // View
uniform mat4 projectionFromView; // Projection
#include "/lib/VertexData.glsl"
out VertexData v;
void main() {
v = fillVertexData();
gl_Position = projectionFromView * viewFromWorld * vec4(v.worldPosition, 1);
}
When compiling the shader via glCompileShaderIncludeARB(vertex, 0, NULL, NULL); I get following error: Error. Message: 0:18(21): error: 'objectPosition' undeclared. The objectPosition vertex attribute declared in MyShader.vert is not recognized.
Whereas if I move the fillVertexData() function to MyShader.vert shader, it works fine.
option B
// NamedString /lib/VertexData.glsl
struct VertexData {
vec3 objectPosition;
vec3 worldPosition;
};
// MyShader.vert
#version 430
#extension GL_ARB_shading_language_include : require
layout(location = 0) in vec3 objectPosition;
uniform mat4 worldFromObject; // Model
uniform mat4 viewFromWorld; // View
uniform mat4 projectionFromView; // Projection
#include "/lib/VertexData.glsl"
out VertexData v;
VertexData fillVertexData() {
VertexData v;
v.objectPosition = objectPosition;
v.worldPosition = vec3(worldFromObject * vec4(objectPosition, 1));
return v
}
void main() {
v = fillVertexData();
gl_Position = projectionFromView * viewFromWorld * vec4(v.worldPosition, 1);
}
This made me think that the extension checks the scope of variables per named string. But that's not the behavior I expect from an #include preprocessor macro system. It should NOT care about variable scopes and just preprocess MyShader.vert and compile that one.
I tried option A via GL_GOOGLE_include_directive and glslangValidator -l MyShader.vert does NOT throw any errors for both options, and generated GLSL code via -E looks correct. Which was my expectation.
I read the extension specifications and it didn't mention that variables that are used in a named string should be declared by the time the extension is processing that named string. Am I doing something wrong? Or is this by design of ARB_shading_language_extension? Any suggestions on how I can keep fillVertexData() in the named string?
By the way, before writing my own #include implementation for my own app, I wanted to exhaust existing solutions. I first tried glslang library. But the preprocessor output I get from it is not compileable GLSL: my version of OpenGL does not support GL_GOOGLE_include_directive and it fills the code with #line directives where the second parameter is NOT an integer but a string (filename) which is not valid GLSL.
Using ARB_shading_language_extension was my second attempt of having reusable GLSL code via #includes.

Related

Why does GLSL Warning tell me varying isn't written to, when it clearly is?

I have never had any problems passing variables from vertex shader to fragment shader. But today, I added a new "out" variable in the vs, and a corresponding "in" variable in the fs. GLSL says the following:
Shader Program: The fragment shader uses varying tbn, but previous shader does not write to it.
Just to confirm, here's the relevant part of the VS:
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 uv;
// plus other layout & uniform inputs here
out DATA
{
vec2 uv;
vec3 tangentViewDir;
mat3 tbn;
} vs_out;
void main()
{
vs_out.uv = uv;
vs_out.tangentViewDir = vec3(1.0);
vs_out.tbn = mat3(1.0);
gl_Position = sys_ProjectionViewMatrix * sys_ModelMatrix * position;
}
And in the FS, it is declared as:
in DATA
{
vec2 uv;
vec3 tangentViewDir;
mat3 tbn;
} fs_in;
Interestingly, all other varyings, like "uv" and all, work. They are declared the same way.
Also interesting: Even though GLSL says the variable isn't written to - it still recognizes the changes when I write to it, and displays those changes.
So is it just a false warning or bug? Even though it tells me otherwise, the value seems to be passed correctly. Why do I receive this warning?
HolvBlackCat pointed me in the right direction - it was indeed a shader mismatch!
I had 2 shader programs, same FS in both, but different VSs, and I forgot to update the outputs of the 2nd VS to match the output layout of the first, so that they both work with the same FS!
Ouch, I guess now that I've run into this error, lesson learnt.
Thank you HolvBlackCat!

GLSL variable not passing from vertex to fragment shader

I'm getting a strange error when trying to pass a float from my vertex to the fragment shader.
Vertex shader:
#version 450
out float someFloat;
void main() {
someFloat = 1.0;
// some code ...
}
Fragment shader:
#version 450
in float someFloat;
void main() {
// some code using someFloat ...
}
This won't work and always pass zero, while this works:
Vertex shader:
#version 450
layout (location = 0) out float someFloat;
void main() {
someFloat = 1.0;
// some code ...
}
Fragment shader:
#version 450
layout (location = 0) in float someFloat;
void main() {
// Some code using someFloat ...
}
But how can I do this without having to use locations ?
According to KHR_vulkan_glsl, which governs the compilation of GLSL into SPIR-V for Vulkan:
When generating SPIR-V, all in and out qualified user-declared (non built-in) variables and blocks (or all their members) must have a shader-specified location. Otherwise, a compile-time error is generated.
Emphasis added. GLSL is not identical between OpenGL and Vulkan.
This of course is because SPIR-V doesn't allow GLSL's resource matching between stages by name (since SPIR-V variables don't have to have names). It only does it by location. And rather than require the compiler to generate locations that will somehow match locations specified by names in other stages, it simply requires users to spell out the locations directly in the shader.
You should have gotten an error from your GLSL compiler.
You need use a varying variable.
Vertex shader:
varying float someFloat;
void main() {
someFloat = 1.0;
// some code ...
}
Fragment shader:
varying float someFloat;
void main() {
// some code using someFloat ...
}

Shaders not working as expected

Using OpenGL 3.2 / GLSL 150 with OpenFrameworks v0.8.3
I'm trying to implement shaders into my programs. My program successfully loads the correct frag and vert files, but I get this glitched visual and error:
[ error ] ofShader: setupShaderFromSource(): GL_FRAGMENT_SHADER shader failed to compile
[ error ] ofShader: GL_FRAGMENT_SHADER shader reports:
ERROR: 0:39: Use of undeclared identifier 'gl_FragColor'
I read this SO answer explaining that gl_FragColor is not supported in GLSL 300, but I'm (pretty sure I'm) not using that version. Regardless, when I change gl_FragColor with an outputColor var, my screen just appears black with no error.
Why isn't my shader appearing as expected? I have a feeling it is either my .vert file / a fundamental misunderstanding of how shapes are drawn from within shaders, or versioning problems.
My simplified program:
.h
#pragma once
#include "ofMain.h" //includes all openGL libs/reqs
#include "GL/glew.h"
#include "ofxGLSLSandbox.h" //addon lib for runtime shader editing capability
class ofApp : public ofBaseApp{
public:
void setup();
void draw();
ofxGLSLSandbox *glslSandbox; //an object from the addon lib
};
.cpp
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
// create new ofxGLSLSandbox instance
glslSandbox = new ofxGLSLSandbox();
// setup shader width and height
glslSandbox->setResolution(800, 480);
// load fragment shader file
glslSandbox->loadFile("shader"); //shorthand for loading both .frag and .vert as they are both named "shader.frag" and "shader.vert" and placed in the correct dir
}
//--------------------------------------------------------------
void ofApp::draw(){
glslSandbox->draw();
}
.vert (just meant to be a pass-through... if that makes sense)
#version 150
uniform mat4 modelViewProjectionMatrix;
in vec4 position;
void main(){
gl_Position = modelViewProjectionMatrix * position;
}
.frag (see 3rd interactive code block down this page for intended result)
#version 150
#ifdef GL_ES
precision mediump float;
#endif
out vec4 outputColor;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float circle(in vec2 _st, in float _radius){
vec2 dist = _st-vec2(0.5);
return 1.-smoothstep(_radius-(_radius*0.01),
_radius+(_radius*0.01),
dot(dist,dist)*4.0);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(circle(st,0.9));
outputColor = vec4( color, 1.0 );
}
I don't see the uniform variables getting set anywhere, which means they take the default values. This means that your matrix is all zeroes.

boost spirit parsing GLSL varyings

Boost::spirit seems to contain so much template magic that I can't understand the docs..
I would like to parse GLSL (OpenGL Shader source) and extract in and out attribute names and their types from the source. I'm restricting GL API version to GL 3.3 so usingsimply GL_ARB_interface_query is no option and I need to read the strings directly from the shader source.
Here is the GLSL source from what I try extract "in vec2 ks_Vertex;" "flat out int SpriteTexID;" parts. Tricky part is that some of the out varyings are in interface block like this:
out VertexData {
smooth vec4 Color;
smooth vec2 TexCoord;
};
I need to extract the "VertexData", "vec4 Color" and "vec2 TexCoord" strings.
The full source:
#version 150
uniform isamplerBuffer ks_MaterialIDBuffer;
in vec2 ks_Vertex;
in vec4 ks_Color;
in vec2 ks_TexCoord;
layout(shared) uniform Camera {
vec2 Position;
vec4 Viewport;
mat4 ModelviewProjMatrix;
mat4 ModelviewMatrix;
mat4 ProjectionMatrix;
};
out VertexData {
smooth vec4 Color;
smooth vec2 TexCoord;
} Out;
flat out int SpriteTexID;
flat out int SpriteMaterialID;
void main()
{
int sprid = gl_VertexID / 4;
ivec4 material = texelFetch(ks_MaterialIDBuffer, sprid);
Out.Color = ks_Color;
Out.TexCoord = ks_TexCoord;
gl_Position = ModelviewProjMatrix * vec4(ks_Vertex, 0.0f, 1.0f);
SpriteTexID = material.r;
SpriteMaterialID = material.g;
}
I especially need the out varying names, but I have no idea how to construct such parser with boost::spirit. I barely made a lexer that counts words.. How do I define such parser with boost::spirit?

OpenGL - Using uniform variable breaks shader

There's a uniform vec3 in my shader that causes some odd behavior. If I use it in any way inside the shader - even if it has no actual effect on anything - the shader breaks and nothing that uses it is rendered.
This is the (vertex) shader:
#version 330 core
layout(std140) uniform ViewProjection
{
mat4 V;
mat4 P;
};
layout(location = 0) in vec3 vertexPosition_modelspace;
smooth out vec3 UVW;
uniform mat4 M;
uniform vec3 cameraPosition;
void main()
{
vec3 vtrans = vec3(vertexPosition_modelspace.x,vertexPosition_modelspace.y,vertexPosition_modelspace.z);
// if(cameraPosition.y == 123456)
// {}
mat4 MVP = P *V *M;
vec4 MVP_Pos = MVP *vec4(vtrans,1);
gl_Position = MVP_Pos;
UVW = vertexPosition_modelspace;
}
If I use it like this, it works fine, but as soon as I uncomment the commented lines, the shader breaks. There's no error on compiling or linking the shader, glGetError() reports no errors either. It happens if 'cameraPosition' is used in ANY way, even if it's meaningless.
This only happens on my laptop however, which is running OpenGL 3.1. On my PC with OpenGL 4.* I don't have this issue.
What's going on here?