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.
Related
I am triing tor read diferent 3D formats using Assimp. My corresponding C++ code looks like this:
void loadScene(string myFile)
{
Importer importer;
const aiScene *scene = importer.ReadFile(myFile, 0);
if(scene) cout<<"OK"<<endl;
else cout<< importer.GetErrorString () <<endl;
}
int main()
{
loadScene("myFile.fbx");
loadScene("myFile.3ds");
loadScene("myFile.obj");
loadScene("myFile.glb");
return 0;
}
and the output:
OBJ: Invalid face indice
OBJ: Invalid face indice
OK
OBJ: Invalid face indice
Can This be fixed? All 4 files, I am triing to read are OK, checked them with some 3D viewer.
I checked the reason for that problem is because Assimp always selects the importer for obj format. The simplest solution would be to force Assimp explicitly to use the right importer, since I know exactly which importer is suitable for which file. Unfortunately it seems like Assimp has no way to select importer explicitly.
So what I did, just added this code:
const std::string::size_type s = pFile.find_last_of('.');
if (s != std::string::npos) {
unsigned int a = GetImporterIndex(_pFile+s);
imp = pimpl->mImporter[a];
}
to const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) and my output looks like this:
OK
Chunk is too large
OK
GLTF: Unsupported binary glTF version
The problem with glb file seems to be because wrong importer is used, it should be gltf2 but gltf used instead.
I've constructed a quick python script that reads a wavefront .obj file and outputs the verticies and faces to files. I have another C++ function that reads these files and creates a mesh based of-of those.
The issue that I'm experiencing is that this works perfectly sometimes, and other time not so much - with the same mesh. E.g. I start my PhysX program, and create 10 of the same objects of the same mesh and some of them look like this:
and others look like this:
The following C++ is the code that loads the verticies and triangles:
bool ModelLoader::LoadVertexFile(const std::string& fileLocation)
{
std::ifstream file(fileLocation);
if (!file) {
std::cerr << "Failed to load vertex data\n";
return false;
}
float x, y, z;
vertexArray.clear();
while (file >> x >> y >> z)
{
vertexArray.push_back(PhysicsEngine::PxVec3(x, y, z));
}
return true;
}
bool ModelLoader::LoadTrianglesFile(const std::string& fileLocation)
{
std::ifstream file(fileLocation);
if (!file) {
std::cerr << "Failed to load vertex data\n";
return false;
}
int x;
triangleArray.clear();
while (file >> x)
{
triangleArray.push_back(x);
}
return true;
}
This is the code for creating constructing the mesh
CustomObject(const PxTransform& pose = PxTransform(PxIdentity), string vertfile = "", string trigfile = "") :
StaticActor(pose)
{
modelLoader = new ModelLoader();
if(!modelLoader->LoadVertexFile(vertfile))
throw new Exception("Failed to load VertexFile.");
if(!modelLoader->LoadTrianglesFile(trigfile))
throw new Exception("Failed to load TrianglesFile.");
PxTriangleMeshDesc mesh_desc;
mesh_desc.points.count = (PxU32)modelLoader->vertexArray.size();
mesh_desc.points.stride = sizeof(PxVec3);
mesh_desc.points.data = &modelLoader->vertexArray.front();
mesh_desc.triangles.count = (PxU32)modelLoader->triangleArray.size();
mesh_desc.triangles.stride = 3 * sizeof(PxU32);
mesh_desc.triangles.data = &modelLoader->triangleArray.front();
CreateShape(PxTriangleMeshGeometry(CookMesh(mesh_desc)));
}
So if anyone can help me figure out whats going wrong it would be really appreciated
I got a problem when I want to import a simple model using assimp, whenever I compile the code it throws:
0xC0000005: Access violation reading location 0x00000000.
I know this is something about a null pointer but I just can't find it, the code goes as follows:
Model::Model(GLchar* path)
{
loadModel(path);
}
void Model::loadModel(std::string path)
{
Assimp::Importer import;
const aiScene* scene = import.ReadFile(
path,
aiProcess_Triangulate |
aiProcess_FlipUVs);
if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){
std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
return;
}
directory = path.substr(0, path.find_last_of('/'));
aiNode* node = scene->mRootNode;
for (GLuint i = 0; i < node->mNumChildren; i++){
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (GLuint i = 0; i < node->mNumChildren; i++){
processNode(node->mChildren[i], scene);
}
}
I use this Model class as a global variable:
//include stuff
//other global variable
Model mymodel("D:/Project/xxx/xxx.obj");
int main(){
//...
return 0;
}
The thing is that the error happens just between the line directory = path.substr(0, path.find_last_of('/')); and the line aiNode* node = scene->mRootNode; so I don't know how to debug it, could anyone tell me how to fix this? I use Visual Studio 2013-64 and assimp-3.1.1.
Thank you very much.
I think the problem could be in this part of the code:
Model::Model(GLchar* path)
{
loadModel(path); // path is declared a string in loadModel function - type conversion might not be happening as expected.
}
Check, if you are getting a correct/valid value in the path variable on the line:
directory = path.substr(0, path.find_last_of('/'));
This link might be helpful:
GLchar could not be resolved
Note: I am not familiar with OpenGL, but looking at the error you are getting this is the first place I would check.
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.
I'm trying to write some code to read a list of file names from a config file named "TextureList.txt" and then use those files to create a shader resource view for each texture. The listing below shows what I currently have:
LPCSTR textures[MAX_TEXTURES];
std::ifstream texturesToLoad;
texturesToLoad.open("TextureList.txt");
int numberOfTextures = 0;
while(!texturesToLoad.eof())
{
std::string textureName;
std::getline(texturesToLoad, textureName);
textures[numberOfTextures] = textureName.c_str();
numberOfTextures++;
char debugMsg[100];
sprintf(debugMsg, "numberOfTextures = %d\n", numberOfTextures);
OutputDebugString(debugMsg);
OutputDebugString(textureName.c_str());
OutputDebugString("\n");
}
for(int i = 0; i < numberOfTextures; i++)
{
d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
textures[i], 0, 0, &colorMap_[i], 0 );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to load the texture image!" );
return false;
}
}
The debugs at the bottom of the while loop show that the file is being read correctly, it obtains all of the file names and calculates the correct number of textures; however it fails when it tries to create the first resource view.
Can anyone tell me where I'm going wrong?
I don't know if it helps but it works if I replace everything above the for loop with hard coded file names using the following line:
const LPCSTR textures[3] = {"tex1.dds", "tex2.dds", "tex3.dds"};