Unity shader: Parser error: syntax error at line 19 - opengl

I was making a shader script in Unity and I got a syntax error.
I don't see any mistake in there, though.
Does anyone else see the trouble maker?
Shader "Custom/Toon" {
Properties {
...
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
...
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
GLSLPROGRAM
...
uniform vec4 _OutlineColor; //Line 19
...

Problem solved.
All I had to do is changing "GLSLPROGRAM" and "ENDGLSL" into "CGPROGRAM" and "ENDCG".

Related

Error code E0065 & E0169 where there shouldnt be

I am going along making my csgo cheat via C++. Everything is going well, until I get to the menu, which throws what appears to be false error messages.
Ive tried doing what visual studios "quick fixes" are. It puts a Semi-colon at the end of "ImGuiWindowFlags_NoTitleBar" and changes the first error to a E0169 as well.
void Menu::Render()
{
ImGui::GetIO().MouseDrawCursor = _visible;
if (!_visible)
return;
const auto sidebar_size = get_sidebar_size();
static int active_sidebar_tab = 0;
//ImGui::PushStyle(_style);
ImGui::SetNextWindowPos(ImVec2{ 0, 0 }, ImGuiSetCond_Once);
ImGui::SetNextWindowSize(ImVec2{ 1000, 400 }, ImGuiSetCond_Once);
// https://github.com/spirthack/CSGOSimple/issues/63
// quick fix
if (ImGui::Begin("testbuild"))
& _visible,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar)) { <line 376
//auto& style = ImGui::GetStyle();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
{
ImGui::BeginGroupBox("##sidebar", sidebar_size);
{
//ImGui::GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders;
render_tabs(sidebar_tabs, active_sidebar_tab, get_sidebar_item_width(), get_sidebar_item_height(), false);
}
ImGui::EndGroupBox();
}
ImGui::PopStyleVar();
ImGui::SameLine();
// Make the body the same vertical size as the sidebar
// except for the width, which we will set to auto
auto size = ImVec2{ 0.0f, sidebar_size.y };
ImGui::BeginGroupBox("##body", size);
if (active_sidebar_tab == TAB_ESP) {
RenderEspTab();
}
else if (active_sidebar_tab == TAB_AIMBOT) {
RenderEmptyTab();
}
else if (active_sidebar_tab == TAB_MISC) {
RenderMiscTab();
}
else if (active_sidebar_tab == TAB_CONFIG) {
RenderConfigTab();
}
ImGui::EndGroupBox();
ImGui::TextColored(ImVec4{ 0.0f, 0.5f, 0.0f, 1.0f }, "FPS: %03d", get_fps());
ImGui::SameLine(ImGui::GetWindowWidth() - 150 - ImGui::GetStyle().WindowPadding.x);
if (ImGui::Button("Unload", ImVec2{ 150, 25 })) {
g_Unload = true;
}
ImGui::End();
}
} <line 418
I expected everything to go away, but it didnt. Error messages:
Error (active) E0065 expected a ';' CSGOSimple 376
Error (active) E0169 expected a declaration CSGOSimple 418
The problem is this line right here:
if (ImGui::Begin("testbuild"))
The last parenthesis at the end closes the if statement. That means it expects the next thing to be some statement. An example of something it would expect:
if(ImGui::Begin("testbuild"))
return; // Notice we need a semicolon here because return is a statement
This is because if statements in C++ can have a statement or a block following it. Since you don't have a semicolon here (because you clearly don't mean for the if statement to end that early) it throws an error.
To fix this, you will need to remove that parenthesis and fix your if statement. It's not completely apparent to me what you actually intend to do here, so you will have to figure that out yourself. But at least you now have an idea of what's happening here.

Camera Shake Not Activating Unreal C++

I am trying to set a camera shake for my character in Unreal C++.
Currently, I declare the instance variable in my header class.
Using log outputs, the code is reaching the right location in the OnFire() function, meaning none of the pointers are null. But the camera shake doesn't work.
UPROPERTY(EditAnywhere)
UCameraShake* CShake;
// And here is how I call it
void AZombieCharacter::BeginPlay(){
SetUpCameraShake();
}
...
void AZombieCharacter::OnFire() {
...
auto CTRLR = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (CTRLR) {
auto CM = CTRLR->PlayerCameraManager;
if (CM) {
CM->PlayCameraShake(CShake->GetClass(), 1.0f);
}
else {
UE_LOG(LogTemp, Warning, TEXT("CANNOT FIND CM"));
}
}
else {
UE_LOG(LogTemp, Warning, TEXT("CANNOT FIND CTRLR"));
}
}
...
void AZombieCharacter::SetUpCameraShake() {
CShake = UCameraShake::StaticClass()->GetDefaultObject<UCameraShake>();
CShake->OscillationDuration = 4.f;
CShake->OscillationBlendInTime = 0.5f;
CShake->OscillationBlendOutTime = 0.5f;
CShake->RotOscillation.Pitch.Amplitude = FMath::RandRange(5.0f, 10.0f);
CShake->RotOscillation.Pitch.Frequency = FMath::RandRange(25.0f, 35.0f);
CShake->RotOscillation.Yaw.Amplitude = FMath::RandRange(5.0f, 10.0f);
CShake->RotOscillation.Yaw.Frequency = FMath::RandRange(25.0f, 35.0f);
}
Thanks.
Play Camera Shake Accepts an UClass / TSubClassOf<UCameraShake> knowing that would expect us to think that this function would eventually construct a new object and ignore the default object options.
I would recommend to subclass the UCameraShake class and use TSubClassOf to store your class type instead of the pointer like CShake. As it may be garbage collected without you knowing who knows?
Here is a C++ tutorial on UCameraShake's.
https://unrealcpp.com/camera-shake/
The reason your shake is not playing is likely having no actual parameters passed to the shake. Only the default ones despite your try to set the default values, it does not seem to take it into account for newly created objects.

GLSL: Force error if any Uniform is not bound

I am using GLSL 1.0 with WebGL 1.0 and 2.0 and I just spent hours troubleshooting an issue that in my opinion should have thrown error before things got started.
I have uniforms and sampler2D's in my fragment Shader. I had changed one line of code and that change had caused no input textures or arrays be bound to the locations of Shader uniforms. The program however runs with no issues but produces zeros when those uniforms are read. For example a call to texture2D(MyTexture, vec2(x,y)) does not throw any errors but rather just returns 0.
Is there anyway for me to force this as an error before or during rendering?
There is no way to make WebGL itself check your errors. You can write your own wrappers if you want to check for errors. As one example there's the webgl-debug context wrapper that calls gl.getError after every single WebGL command.
Following a similar pattern you could try to check for not setting uniforms either by wrapping all the functions related to drawing, programs, uniforms, attributes, etc. or by just making functions you call
function myUseProgram(..args..) {
checkUseProgramStuff();
gl.useProgram(..);
}
function myDrawArrays(..args..) {
checkDrawArraysStuff();
gl.drawArrays(..args..);
}
For uniforms you'd need to track when a program linked successfully then loop over all of its uniforms (which you can query). Track what the current program is. Track calls to gl.uniform to track if uniforms are set.
Here's an example
(function() {
const gl = null; // just to make sure we don't see global gl
const progDB = new Map();
let currentUniformMap;
const limits = {};
const origGetUniformLocationFn = WebGLRenderingContext.prototype.getUniformLocation;
function init(gl) {
[gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS].forEach((pname) => {
limits[pname] = gl.getParameter(pname);
});
}
function isBuiltIn(info) {
const name = info.name;
return name.startsWith("gl_") || name.startsWith("webgl_");
}
function addProgramToDB(gl, prg) {
const uniformMap = new Map();
const numUniforms = gl.getProgramParameter(prg, gl.ACTIVE_UNIFORMS);
for (let ii = 0; ii < numUniforms; ++ii) {
const uniformInfo = gl.getActiveUniform(prg, ii);
if (isBuiltIn(uniformInfo)) {
continue;
}
const location = origGetUniformLocationFn.call(gl, prg, uniformInfo.name);
uniformMap.set(location, {set: false, name: uniformInfo.name, type: uniformInfo.type, size: uniformInfo.size});
}
progDB.set(prg, uniformMap);
}
HTMLCanvasElement.prototype.getContext = function(origFn) {
return function(type, ...args) {
const ctx = origFn.call(this, type, ...args);
if (ctx && type === 'webgl') {
init(ctx);
}
return ctx;
}
}(HTMLCanvasElement.prototype.getContext);
// getUniformLocation does not return the same location object
// for the same location so mapping a location to uniform data
// would be a PITA. So, let's make it return the same location objects.
WebGLRenderingContext.prototype.getUniformLocation = function(origFn) {
return function(prg, name) {
const uniformMap = progDB.get(prg);
for (const [location, uniformInfo] of uniformMap.entries()) {
// note: not handling names like foo[0] vs foo
if (uniformInfo.name === name) {
return location;
}
}
return null;
};
}(WebGLRenderingContext.prototype.getUniformLocation);
WebGLRenderingContext.prototype.linkProgram = function(origFn) {
return function(prg) {
origFn.call(this, prg);
const success = this.getProgramParameter(prg, this.LINK_STATUS);
if (success) {
addProgramToDB(this, prg);
}
};
}(WebGLRenderingContext.prototype.linkProgram);
WebGLRenderingContext.prototype.useProgram = function(origFn) {
return function(prg) {
origFn.call(this, prg);
currentUniformMap = progDB.get(prg);
};
}(WebGLRenderingContext.prototype.useProgram);
WebGLRenderingContext.prototype.uniform1i = function(origFn) {
return function(location, v) {
const uniformInfo = currentUniformMap.get(location);
if (v === undefined) {
throw new Error(`bad value for uniform: ${uniformInfo.name}`); // do you care? undefined will get converted to 0
}
const val = parseFloat(v);
if (isNaN(val) || !isFinite(val)) {
throw new Error(`bad value NaN or Infinity for uniform: ${uniformInfo.name}`); // do you care?
}
switch (uniformInfo.type) {
case this.SAMPLER_2D:
case this.SAMPLER_CUBE:
if (val < 0 || val > limits[this.MAX_COMBINED_TEXTURE_IMAGE_UNITS]) {
throw new Error(`texture unit out of range for uniform: ${uniformInfo.name}`);
}
break;
default:
break;
}
uniformInfo.set = true;
origFn.call(this, location, v);
};
}(WebGLRenderingContext.prototype.uniform1i);
WebGLRenderingContext.prototype.drawArrays = function(origFn) {
return function(...args) {
const unsetUniforms = [...currentUniformMap.values()].filter(u => !u.set);
if (unsetUniforms.length) {
throw new Error(`unset uniforms: ${unsetUniforms.map(u => u.name).join(', ')}`);
}
origFn.call(this, ...args);
};
}(WebGLRenderingContext.prototype.drawArrays);
}());
// ------------------- above is wrapper ------------------------
// ------------------- below is test ---------------------------
const gl = document.createElement('canvas').getContext('webgl');
const vs = `
uniform float foo;
uniform float bar;
void main() {
gl_PointSize = 1.;
gl_Position = vec4(foo, bar, 0, 1);
}
`;
const fs = `
precision mediump float;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, vec2(0));
}
`;
const prg = twgl.createProgram(gl, [vs, fs]);
const fooLoc = gl.getUniformLocation(prg, 'foo');
const barLoc = gl.getUniformLocation(prg, 'bar');
const texLoc = gl.getUniformLocation(prg, 'tex');
gl.useProgram(prg);
test('fails with undefined', () => {
gl.uniform1i(fooLoc, undefined);
});
test('fails with non number string', () => {
gl.uniform1i(barLoc, 'abc');
});
test('fails with NaN', () => {
gl.uniform1i(barLoc, 1/0);
});
test('fails with too large texture unit', () => {
gl.uniform1i(texLoc, 1000);
})
test('fails with not all uniforms set', () => {
gl.drawArrays(gl.POINTS, 0, 1);
});
test('fails with not all uniforms set',() => {
gl.uniform1i(fooLoc, 0);
gl.uniform1i(barLoc, 0);
gl.drawArrays(gl.POINTS, 0, 1);
});
test('passes with all uniforms set', () => {
gl.uniform1i(fooLoc, 0);
gl.uniform1i(barLoc, 0);
gl.uniform1i(texLoc, 0);
gl.drawArrays(gl.POINTS, 0, 1); // note there is no texture so will actually generate warning
});
function test(msg, fn) {
const expectFail = msg.startsWith('fails');
let result = 'success';
let fail = false;
try {
fn();
} catch (e) {
result = e;
fail = true;
}
log('black', msg);
log(expectFail === fail ? 'green' : 'red', ' ', result);
}
function log(color, ...args) {
const elem = document.createElement('pre');
elem.textContent = [...args].join(' ');
elem.style.color = color;
document.body.appendChild(elem);
}
pre { margin: 0; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
The code above only wraps gl.uniform1i. It doesn't handle arrays of uniforms nor does it handle individual array element locations. It does show one way to track uniforms and whether or not they've been set.
Following similar pattern you could check that each texture unit has a texture assigned etc, that each attribute is turned on, etc...
Of course you could also write your own WebGL framework that tracks all that stuff instead of hacking the WebGL context itself. In other words for example three.js could track that all it's uniforms are set at a higher level than the WebGL level and your own code could do something similar.
As for why WebGL doesn't emit errors there are lots of reasons. For one, not setting a uniform is not an error. Uniforms have default values and it's perfectly fine to use the default.
The browser does catch some problems but because WebGL is pipelined it can't give you the error at the moment you issue the command without a huge slow down in performance (the debug context mentioned above will do that for you). So, the browser can sometimes give an warning in the console but it can't stop your JavaScript at the point you issued the command. It might not be that helpful anyway is the only place it can often give an error is at draw time. In other words to 30-100 commands issued before to setup WebGL state are not an error until you draw since you could fix that state at anytime before you draw. So you get the error on draw but that doesn't tell you which of the 30-100 previous commands caused the issue.
Finally there's the philosophical issue of trying to support native ports from OpenGL/OpenGL ES via emscripten or WebAssembly. Many native apps ignore
lots of GL errors and yet still run. This is one reason why WebGL doesn't throw, to stay compatible with OpenGL ES (as well as the reason above). It's also why most WebGL implementations only show a few errors and then print "no more webgl errors will be shown" since browsers didn't want programs that ignore their WebGL errors to fill memory with logging messages.
Fortunately if you really want it you can write your own checking.

OpenGL showing blank screen. Maybe due to shaders?

My OpenGL ES application isn't working. I'm using SDL for windowing management, and it holds the context. After looking around, I noticed that the vertex shader and the fragment shader showed up as 0 on the debugger. Even the program was 0. Could this be a reason? I followed my shader compiling and linking code to a template that was previously made.
If it is, what is wrong? Here is the code:
GLuint ShaderHelper::compileShader(GLenum type, std::string fileName) {
std::string fileContents;
std::ifstream fin;
std::string path;
// Getting the necessary path...
// These are abstractions for getting file contents
// from the main bundle.
if (type == GL_VERTEX_SHADER) {
FileOpener opener;
path = opener.retriveFileFromBundle(fileName, "vsh");
} else if (type == GL_FRAGMENT_SHADER) {
FileOpener opener;
path = opener.retriveFileFromBundle(fileName, "fsh");
} else {
std::cout << "ERROR: Invalid shader type at filename " << fileName << std::endl;
exit(1);
}
fin.open(path);
if (!fin.is_open()) {
std::cout << "ERROR: Failed to open file " << fileName << std::endl;
exit(1);
}
// Retrieving the string from the file...
while (!fin.eof()) {
char CLine[255];
fin.getline(CLine, 255);
std::string line = CLine;
fileContents = fileContents + line;
fileContents = fileContents + " \n";
}
fin.close();
// I'm creating these variables because a pointer is needed for
// glShaderSource
GLuint shaderHandle = glCreateShader(type);
const GLint shaderStringLength = (GLint)fileContents.size();
const GLchar *shaderCString = fileContents.c_str();
glShaderSource(shaderHandle, 1, &shaderCString, &shaderStringLength);
glCompileShader(shaderHandle);
return shaderHandle;
}
void ShaderHelper::linkProgram(std::vector<GLuint *> shaderArray) {
program = glCreateProgram();
for (int i = 0; i < shaderArray.size(); i++) {
glAttachShader(program, *shaderArray[i]);
}
glLinkProgram(program);
}
void ShaderHelper::addUniform(uniform_t uniform) {
std::string name = uniform.name;
uniforms[name] = uniform;
// With that step done, we need to assign the location...
uniforms[name].location = glGetUniformLocation(program, uniforms[name].name.c_str());
}
EDIT: After suggestions, I ran my code through glError(). I fixed an error, but I still got a blank screen. I'm no longer getting 0 as my shader values. I set glClearColor to a white image, and it's just appearing pure white. I adjusted numbers in the MV matrix and projection matrix, but there's still nothing at all. I disabled face culling, but still nothing. Also, shaders are compiling and linking fine. So now what?
The dreaded blank screen can be caused by a variety of problems:
Your context is not created correctly or you're not presenting your scene properly. Does changing your clear color to something else than black show anything?
Your transformation matrix is wrong. How are you setting up the position of the "camera"? Are you using something like GLM to set up a matrix? If so, have a look at glm::perspective() and glm:::lookAt(). Make sure you're passing the matrix to the shader and that you're using it to set gl_Position in your vertex shader.
The geometry you're trying to display is facing away from the viewer. Try glDisable(GL_CULL_FACE). If it works, reverse the order of your vertices.
An OpenGL call is failing somewhere. Make sure you check glGetError() after every call. I usually have something like the following:
struct gl_checker
{
~gl_checker()
{
const auto e = glGetError();
assert(e == GL_NO_ERROR);
}
};
template <class F>
inline auto gl_call(F f) -> decltype(f())
{
gl_checker gc;
return f();
}
which can be used like this:
gl_call([]{ glDisable(GL_CULL_FACE); });
Your shaders fail to compile or link. Have a look at glGetShaderiv() with GL_COMPILE_STATUS and glGetProgramiv() with GL_LINK_STATUS. If they report an error, have a look at glGetShaderInfoLog() and glGetProgramInfoLog().
As for the partial code you provided, I see nothing strictly wrong with it. Providing the shaders and a smaller, complete program might help with finding the problem.

Opengl error 1281 when trying to glUseProgram

Any ideas how I could debug this opengl error further? 1281
I'm loading source from files, compiling, linking and then trying to check for errors after glUseProgram
In my object's draw method ..
log.info(gl2.glIsProgram(shaderProgram)); // true
gl2.glUseProgram(shaderProgram);
int error;
while ((error = gl2.glGetError()) != GL2.GL_NO_ERROR) {
throw new RuntimeException("glUseProgram" + ": glError " + error);
}
Output ..
[13:38:08] INFO (IARectangle.java:99) - true
java.lang.RuntimeException: glUseProgram: glError 1281
This is how I load my shader source, from .glsl files ..
Vector<Integer> shaders = new Vector<Integer>();
try {
shaders.add(compileSource(
loadSource("shaders/vertexShader.glsl"),
loadSource("shaders/fragmentShader.glsl")));
return shaders;
} catch (Exception e) {
e.printStackTrace();
return shaders;
}
public String[] loadSource(String filename){
StringBuilder sb = new StringBuilder();
try {
InputStream is = getClass().getClassLoader().getResourceAsStream(filename);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return new String[] { sb.toString() };
}
public final int compileSource(final String[] vertexSource, final String[] fragmentSource) throws Exception {
vertexShaderProgram;
int fragmentShaderProgram;
int shaderProgram;
// load vertexShader source, compile and verify
vertexShaderProgram = gl2.glCreateShader(GL2.GL_VERTEX_SHADER);
gl2.glShaderSource(vertexShaderProgram, 1, vertexSource, null, 0);
gl2.glCompileShader(vertexShaderProgram);
verifyCompile(gl2, vertexShaderProgram);
// load fragmentShader source, compile and verify
fragmentShaderProgram = gl2.glCreateShader(GL2.GL_FRAGMENT_SHADER);
gl2.glShaderSource(fragmentShaderProgram, 1, fragmentSource, null, 0);
gl2.glCompileShader(fragmentShaderProgram);
verifyCompile(gl2, fragmentShaderProgram);
shaderProgram = gl2.glCreateProgram();
gl2.glAttachShader(shaderProgram, vertexShaderProgram);
gl2.glAttachShader(shaderProgram, fragmentShaderProgram);
gl2.glLinkProgram(shaderProgram);
IntBuffer intBuffer = IntBuffer.allocate(1);
gl2.glGetProgramiv(shaderProgram, GL2.GL_LINK_STATUS, intBuffer);
if (intBuffer.get(0) != 1){
String infoLog = null;
gl2.glGetProgramiv(shaderProgram, GL2.GL_INFO_LOG_LENGTH, intBuffer);
int size = intBuffer.get(0);
log.error("Program link error: ");
if (size > 0) {
ByteBuffer byteBuffer = ByteBuffer.allocate(size);
gl2.getGL2().glGetProgramInfoLog(shaderProgram, size, intBuffer, byteBuffer);
byte[] sizeBytes = new byte[size];
byteBuffer.get(sizeBytes, 0, size);
infoLog = new String(sizeBytes);
log.error("info: " + infoLog);
} else {
log.error("Unknown");
}
System.exit(1);
return shaderProgram;
} else {
return shaderProgram;
}
}
Vertex shader source ..
#version 120
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
//gl_Position = uMVPMatrix * vPosition;
}
Fragment shader source ..
#version 120
uniform vec4 vColor;
void main() {
gl_FragColor = vColor;
}
At first glance, I'm not sure why glGetError is returning an error code. But to answer your specific question of 'How can I debug this error further?', I do have a suggestion.
Change your draw code to this:
// Logging errors before the call to glUseProgram
int error;
while ((error = gl2.glGetError()) != GL2.GL_NO_ERROR) {
log.info(error);
}
log.info(gl2.glIsProgram(shaderProgram)); // true
gl2.glUseProgram(shaderProgram);
int error;
while ((error = gl2.glGetError()) != GL2.GL_NO_ERROR) {
throw new RuntimeException("glUseProgram" + ": glError " + error);
}
Note that the difference here is we've added a block of code to log errors returned by glGetError before the call to glUseProgram. The reason is because the error is not necessarily originating in your call to glUseProgram. If you see the 1281 error logged using the code above, you can determine that the error is actually originating from an OpenGL call made before the glUseProgram call.
Take a look at the documentation for glGetError:
glGetError returns the value of the error flag. Each detectable error
is assigned a numeric code and symbolic name. When an error occurs,
the error flag is set to the appropriate error code value. No other
errors are recorded until glGetError is called, the error code is
returned, and the flag is reset to GL_NO_ERROR.
So, if one of your earlier OpenGL calls (perhaps something in your compileSource function, for example) recorded the 1281 error, and you did not call glGetError anywhere between that point and your call to glUseProgram, you can not reasonably assume that the error is actually originating from the glUseProgram call.
In summary, glGetError does not return the most recent error recorded by an OpenGL call. You need to call glGetError with more granularity in order to pinpoint where the error is originating. This will allow you to troubleshoot the issue you're having and determine exactly which OpenGL call is recording the error.