@Capehill I took just a simple "load shader" example done for OGLES2/SDL2 by Hans from his book, and in Tutorial02 simply replaced his shaders on those in question: Linking fail.
Phew, so its not Irrlicht Engine or GL4ES fault, we left now with warp3dnova and olges2.
/** Encapsulates the data for a single vertex.
* Must match the vertex shader's input.
*/
typedef struct Vertex_s {
float position[2];
} Vertex;
/** Creates the Vertex Buffer Object (VBO) containing
* the given vertices.
*
* @param vertices pointer to the array of vertices
* @param numVertices the number of vertices in the array
*/
GLuint vboCreate(const Vertex *vertices, GLuint numVertices) {
// Create the Vertex Buffer Object
GLuint vbo;
int nBuffers = 1;
glGenBuffers(nBuffers, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// Copy the vertex data in, and deactivate
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Check for problems
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
// Failed
glDeleteBuffers(nBuffers, &vbo);
SDL_Log("Creating VBO failed, code %u\n", err);
vbo = 0;
}
return vbo;
}
/** Frees the VBO.
*
* @param vbo the VBO's name.
*/
void vboFree(GLuint vbo) {
glDeleteBuffers(1, &vbo);
}
const unsigned int DISP_WIDTH = 640;
const unsigned int DISP_HEIGHT = 480;
int main(int argc, char *args[]) {
// The window
SDL_Window *window = NULL;
// The OpenGL context
SDL_GLContext context = NULL;
// Init SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
return 10;
}
// Setup the exit hook
atexit(SDL_Quit);
// Request OpenGL ES 3.0
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
// Want double-buffering
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// Create the window
window = SDL_CreateWindow("GLES3+SDL2 Tutorial", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, DISP_WIDTH, DISP_HEIGHT,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!window) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
"Couldn't create the main window.", NULL);
return EXIT_FAILURE;
}
context = SDL_GL_CreateContext(window);
if (!context) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
"Couldn't create an OpenGL context.", NULL);
return EXIT_FAILURE;
}
// Clear to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Update the window
SDL_GL_SwapWindow(window);
// Load the shader program and set it for use
GLuint shaderProg = shaderProgLoad("Simple2D.vert", "Simple2D.frag");
if (!shaderProg) {
// Error messages already displayed...
return EXIT_FAILURE;
}
glUseProgram(shaderProg);
// Create the triangle
const Vertex vertices[] = {
{ 0.0f, -0.9f },
{ 0.9f, 0.9f },
{-0.9f, 0.9f } };
GLsizei vertSize = sizeof(vertices[0]);
GLsizei numVertices = sizeof(vertices) / vertSize;
GLuint triangleVBO = vboCreate(vertices, numVertices);
if (!triangleVBO) {
// Failed. Error message has already been printed, so just quit
return EXIT_FAILURE;
}
// Set up for rendering the triangle (activate the VBO)
GLuint positionIdx = 0; // Position is vertex attribute 0
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
glVertexAttribPointer(positionIdx, 2, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (const GLvoid*)0);
glEnableVertexAttribArray(positionIdx);
// Now draw!
glDrawArrays(GL_TRIANGLES, 0, numVertices);
// Update the window
SDL_GL_SwapWindow(window);
// Wait for the user to quit
bool quit = false;
while (!quit) {
SDL_Event event;
if (SDL_WaitEvent(&event) != 0) {
if (event.type == SDL_QUIT) {
// User wants to quit
quit = true;
}
}
}
#include <cstdio>
#include <cstdlib>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengles2.h>
#include "Shader.h"
#ifdef _MSC_VER
#pragma warning(disable:4996) // Allows us to use the portable fopen() function
without warnings
#endif
/** Gets the file's length.
*
* @param file the file
*
* @return size_t the file's length in bytes
*/
static size_t fileGetLength(FILE *file) {
size_t length;
size_t currPos = ftell(file);
fseek(file, 0, SEEK_END);
length = ftell(file);
// Return the file to its previous position
fseek(file, currPos, SEEK_SET);
return length;
}
/** Loads and compiles a shader from a file.
*
* This will print any errors to the console.
*
* @param filename the shader's filename
* @param shaderType the shader type (e.g., GL_VERTEX_SHADER)
*
* @return GLuint the shader's ID, or 0 if failed
*/
static GLuint shaderLoad(const char *filename, GLenum shaderType) {
FILE *file = fopen(filename, "r");
if (!file) {
SDL_Log("Can't open file: %s\n", filename);
return 0;
}
size_t length = fileGetLength(file);
// Alloc space for the file (plus '\0' termination)
GLchar *shaderSrc = (GLchar*)calloc(length + 1, 1);
if (!shaderSrc) {
SDL_Log("Out of memory when reading file: %s\n", filename);
fclose(file);
file = NULL;
return 0;
}
fread(shaderSrc, 1, length, file);
// Done with the file
fclose(file);
file = NULL;
// Create the shader
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar**)&shaderSrc, NULL);
free(shaderSrc);
shaderSrc = NULL;
// Compile it
glCompileShader(shader);
GLint compileSucceeded = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileSucceeded);
if (!compileSucceeded) {
// Compilation failed. Print error info
SDL_Log("Compilation of shader %s failed:\n", filename);
GLint logLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
GLchar *errLog = (GLchar*)malloc(logLength);
if (errLog) {
glGetShaderInfoLog(shader, logLength, &logLength, errLog);
SDL_Log("%s\n", errLog);
free(errLog);
}
else {
SDL_Log("Couldn't get shader log; out of memory\n");
}
glDeleteShader(shader);
shader = 0;
}
return shader;
}
During porting an SDL2+GLES2 based app a crash inside ogles2.library has been discovered if the app does not delete the context before quit:
Crash log for task "acidwarp"
Generated by GrimReaper 53.19
Crash occured in module ogles2.library at address 0x7F4E4728
Type of crash: DSI (Data Storage Interrupt) exception
Alert number: 0x80000003
@NPFrandsen That little mistake, it needs ogles3.1 and warp3dnova 1.83, not 1.85. Both come with an Enhancer package which you need to buy from Amikit.
Is anybody using renderbuffer objects as framebuffer depth attachments? My FBO is otherwise rendering fine but as soon as I try to attach an RBO, the result becomes pixel noise.
FBO is complete, context has 16-bit depth, depth testing is enabled and there are no GL errors.
EDIT: solved, as I have multiple FBOs, I removed the unnecessary depth attachment from post-processing FBOs and left it only for the 3D rendering target, so depth testing is now done only once.
I was wondering, if i still hvae graphical glitches in the OGLES2 SDL2 version of ScummVM, but not in the OpenGL SDL2 version, hsould i report them here or in the SDL2 thread?
I'd say here, since it sounds the obvious, but i was wrong so many times in the past...
SDL doesn't draw anything when application uses OpenGL context (application calls OpenGL and finally swaps the buffer) thus SDL shouldn't be blamed for any glitches in my opinion. Issue is either on application side or somewhere in OpenGL / driver side.
Probably stupid question, but does Enhancer Core feature the ogles2.library as well?
Say, i want to compile ScummVM with OGLES2 support Will everyone with a supported Graphics card AND Enhancer Core be able to use it? Or do the people still have to buy the full release to get ogles2?
The readme says it should...but i want to make sure. Quote:
What is the Enhancer Software Core?
It is a free-of-charge version of the Enhancer Software containing classes, libraries and system files for users who have not purchased any version of the Enhancer Software previously. It also contains the SDK for developers to build their own projects around the Enhancer Software.
The files contained in it are essential to run ***any*** applications, utilities or programs created with the Enhancer Software.
Important Note: if you previously purchased any other edition of the Enhancer Software you will not need to register for access to this edition.
Although the Enhancer Software Core is free of charge, it contains copyright files and must only be distributed on this website subject to the AmiSphere terms/conditions and the software's End User Licence Agreement. No Enhancer Software components may be copied or distributed without express written permission from the copyright holder. AmiSphere user registration is required to access the files.
@All I hope Daniel doesn't mind if i update that topic, as it just looses around other topics, so .. Few days ago 3.3 version out for beta, there is full list of changes since 3.1:
3.2 changes
Quote:
- Fix: under certain circumstances DBOs / VBOs were falsely allowed to be modified even if still in use by Nova. This could cause flickering triangles and similar glitches. The latest improvements in Nova revealed this issue. Before it apparently happend so rarely that it went unnoticed. - Fix: glFinish would not actually wait for things to finish if the previous operation was a glFlush or an OpenGL state change (e.g. glEnable or whatever, which trigger an implicit flush internally). This could in theory result in incomplete frames being displayed. - Fix: glReadPixels would not wait for things to finish before starting to read. This could result in incomplete frame data to be read. - Fix: glGetError sometimes returned a wrong error code. - glGetString GL_SHADING_LANGUAGE_VERSION is now returning "OpenGL ES GLSL ES 1.0" - Fix: glMapBufferOES with the flag GL_READ_WRITE(_OES) didn't instruct Nova to read-back the current data. So effectively it acted like GL_WRITE_ONLY(_OES). This worked as long as the user updated the whole buffer or as long as Nova provided a shadow-buffer with the latest data. However it now failed with latest Nova drivers because shadow-buffers are no longer used. - Fix: Nova doesn't support 8bit index VBOs, therefore ogles2.lib contains an emulation mechanism for those. For each such VBO an internal 32bit index VBO is being created and kept in sync. This syncing requires a read-back and due to a typo Nova wasn't told to do so. This in turn means that the data read for the sync was undefined. Until now this wasn't actually the case because Nova used a shadow-buffer, so even though not explicitely requested, the data was there and in the expected format. To sum it up: glDrawElements with a bound element array with 8 or 16 bit indices caused render garbage with the latest Nova versions. - Fix: specs violation. The IDs returned by glCreateShader and glCreateProgram were independently generated. However, the standard says that the shader IDs' "name space is shared with program objects", a fact which I overread, grrmbl. For an OpenGL ES 2 implementation by itself this violation isn't really a problem but it turned out to be the source for an issue related with GL4ES: In std. GL, which GL4ES implements based on OGLES2, there's a function glGetObjectParameters which accepts shader- or program-IDs as first parameter. Now due to this bug in ogles2.lib those IDs were not unique, so that this function was not able to distinguish between shader- and program-IDs, which in turn resulted in nonsense behaviour. Thanks to George for rereading the OGLES2 specs and correcting me on that, as I asumed a bug in GL4ES here. Now the the IDs returned by glCreateShader and glCreateProgram are unique in the shared UINT32 number space. - Cleanup: removed any already unused code which handled own vertex-data endian swapping. - Cleanup: removed any already unused code which handled own element index endian swapping. - Reworked the whole VBO handling because there were subtle flaws related to Nova's internal endian conversion. In a nutshell the root of the problem is the fact that Nova applies its endian conversion when data is being written into a VBO and doesn't care if the data-format changes. Unfortunately this is a problem with the typical workflow of an OpenGL application which usually first fills a VBO and defines the format of the data later. In that case Nova asumes a default UINT32-like data-type for all the data and endian-convert the whole buffer accordingly upon fill. This works as long as there's only stuff like floats in the buffer, in general data with elements of 4-bytes size which require endian conversion. But if there's e.g. something like RGBA UBYTE[4] color data which must not be endian-converted, things begin to break. By the time ogles2 knows the real data format, Nova will already have falsely converted it. There are other situations where this problem arises and to work around all those issues ogles2.library now mirrors the VBO data and only physically updates the internal Nova-VBO's buffer right before it's going to be used for a draw call. It also keeps track of the concrete data-type of each of a VBOs arrays and enforces a data-copy if the endianess of one of those changes. - Added support for Nova's new tag W3DNTag_OriginLowerLeft. There was a problem with Nova in combination with FBOs when rendering to a texture. Then the fragment-shader's optional input gl_FragCoord worked in a vertically flipped fashion, the internally flipped coordinate system of a texture (compared to a "regular" bitmap's coordinate system) was not taken into account. Latest Nova 54.14 now provides a way to toggle gl_FragCoord's behaviour upon texture / bitmap binding, a feature which is now being used and therefore fixes the problem (e.g. weird graphic bugs in ScummVM). - Fix: a typo in the VBO mirror implementation sometimes lead to unnecessary large VBO-writes. This fix resolves the rather significant performance drop which the game Spencer suffered after I made the complex VBO rework mentioned above. - Fix: at one location a conditional submit/waitdone subroutiene call was missing in the VBO implementation. In rare situations this effectively caused draw-call N being drawn with vertex data of the following draw-call N+1. As a result the SDL2 testsprite2 example (with batching disabled!) appeared to only draw a fraction of its 100 smileys. In reality 100 smileys were drawn, but many of them at the same location... - Fix: one of the rather cheap but effective optimizations in the new VBO implementation didn't work if the client used a pretty uncommon (to not say dumb) drawing strategy: the SDL2 testsprite2 example (with batching enabled!) would only render garbage. The reason was that this thing draws its different geometry by adjusting its VBO array offsets, essentially moving a window through the VBO's arrays. This essentially leaves huge areas in the VBO in an undefined state initially - which for Nova generally means: little endian. The optimization now prevented the required VBO-rewrites because it detected that the actual data-type per array didn't change - not taking into account that Nova was only told the types of a tiny subset of that array. Fixing this resolved the distorted background geometry with this example. However, the smileys didn't show up because there was another bug. Actually it was a leftover of the old VBO stuff. It sometimes caused VBOs to be marked for drawing too early in the process. As a result it could sort-of get out of sync and already have the layout for the next draw-call but keep the vertex data of the previous one. All this also fixes some visual glitches with Super Tuxkart. - Fix: under certain rare circumstances a crash in combination with index-array VBOs could happen if the respective VBO was enlarged at just the wrong time, resulting in a deletion of the internal emu-index-VBO (see above) which was probably still in use. With this fix the gl-related crashs in LMGUI test cases are gone. - Fix: the result of glCopyTexImage2D and glCopyTexSubImage2D was upside-down. - Fix: added an extra size check to the mirror-VBO-writer to avoid buffer overwrites triggered by certain corner cases with "uncommon" element-array uses in which the index-VBO contains much larger indices than the respective array-VBOs are sized for. This fixes crashs with ScummVM. - Fix: glGetUniform ignored the program-parameter and queried the currently bound program instead. - It is now possible to use glReadPixels on an FBO with a texture as color-attachment. Nova doesn't support reading a texture's pixel data, which is why this feature wasn't implemented until now. To support it in ogles2 nevertheless the FBO's texture is now used to internally render a quad into a hidden framebuffer with a std. bitmap which in turn can be read. To not create any side-effects a dedicated seperate render-state is being used. - Credits for testing go to kas1e, Capehill and afxgroup. - version set to 3.2 (15.4.2022)
3.3 changes
Quote:
- Fix: querying GL_RED, GL_GREEN, GL_BLUE or GL_ALPHA returned 0 if the current frame-buffer was an FBO with a texture being used as color-attachement. - New aglCreateContext2 tag OGLES2_CCT_SHARE_WITH <ogles2-context-pointer>. This optional tag instructs ogles2 to share the same internal Nova-context (with a different render-state-object) and the same set of textures, VBOs, shaders and shader-programs of the given other gl-context. If you don't supply this tag (which is the default behaviour, of course) then the newly created context is autarkic. Reworked many many internals to properly support resource sharing. Also made lots of code cleanup in the process. This was huge. - I'm tired of malformed programs wasting everybody's time by causing undefined behaviour / crashs because they illegally call gl-functions without an active context. Usually I'm a friend of not doing more work than necessary. Which in this case means that there were no checks if there's a valid gl-context inside public gl-commands. Which is standard compliant. Quote from the OpenGL ES 2.0 specs: "Issuing GL commands when the program is not connected to a context results in undefined behavior." However, I now added context-sanity checks to ALL those gl-commands because there are so many malformed programs around, e.g. Super Tuxkart, Night of The Zombies, Neverball, to name a few. - glGetString(GL_VERSION) now returns a string starting with OpenGL ES 2.0 instead of 2 without the minor version number. - glGetString(GL_SHADING_LANGUAGE_VERSION) now returns "OpenGL ES GLSL ES 1.4" instead of 1.0. - The extension functions glProgramBinary / glGetProgramBinary have been improved to also store and restore the attribute bindings. The binary format has been changed accordingly, glGetProgram with parameter GL_PROGRAM_BINARY_LENGTH_OES and glGet with parameter GL_PROGRAM_BINARY_FORMATS_OES reflect those changes too. That makes GL4ES' precompiled shader program feature (.psa files) fully usable. - Credits for testing go to kas1e and Capehill. - version set to 3.3 (30.4.2022)
@Capehill Btw, i remember you start working on ogles2 version of Quake3 (or it was opengl2.x version? ) with shaders and stuff, were you progress futher ? Or it's all stops because of missing OpImageSampleDrefImplicitLod ?
ioquake3 renderergl2 (I suppose it's OpenGL 2.x -based): yes, however port has been stuck in the same state due to missing op. With bad luck there are more missing stuff - I should probably try to compile all its shaders.