#if (!defined(ECERE_VANILLA) && !defined(ECERE_ONEDRIVER))
import "OpenGLDisplayDriver"
+
+#define near _near
+#define far _far
+#include "gl123es.h"
+#undef near
+#undef far
#endif
public class GLCapabilities : uint
{
public:
- bool legacy :1;
- bool shaders :1;
- bool nonPow2Textures :1;
+ // Expect reloading graphics
+ bool compatible :1;
bool vertexBuffer :1;
- bool frameBuffer :1;
-
- // To be able to disable these at runtime independently...
- bool immediate :1;
- bool fixedFunction :1;
bool quads :1;
bool intAndDouble :1;
+ bool legacyFormats :1;
+ bool nonPow2Textures :1;
+ bool vertexPointer :1;
+
+ // Should be able to toggle without reloading
+ bool legacy :1;
+ bool shaders :1;
+ bool fixedFunction :1;
+ bool immediate :1;
+ bool frameBuffer :1;
+ bool pointSize :1;
+ bool vao :1;
+ bool select :1;
// bool mapBuffer :1;
+
+ bool debug :1;
};
public enum RenderState { fillMode = 1, depthTest, depthWrite, fogDensity, fogColor, blend, ambient, alphaWrite, antiAlias, vSync };
__attribute__((unused)) static void DummyFunction()
{
+#if !defined(__EMSCRIPTEN__)
Mutex { };
+#endif
}
public class DisplayDriver
virtual bool ::ConvertBitmap(DisplaySystem, Bitmap, PixelFormat, ColorAlpha *);
// Converts an LFB bitmap into an offscreen bitmap for this device
- virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool);
+ virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool mipMaps, int cubeMapFace);
// Font loading
virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade);
public enum Alignment { left, right, center };
public enum ClearType { colorBuffer, depthBuffer, colorAndDepth };
-subclass(DisplayDriver) GetDisplayDriver(const char * driverName)
-{
- if(driverName)
- {
- OldLink link;
- for(link = class(DisplayDriver).derivatives.first; link; link = link.next)
- {
- subclass(DisplayDriver) displayDriver = link.data;
- if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName))
- return displayDriver;
- }
- }
- return null;
-}
-
-DisplaySystem GetDisplaySystem(const char * driverName)
-{
- subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
- return displayDriver ? displayDriver.displaySystem : null;
-}
-
define textCellW = 8;
define textCellH = 16;
float multiplier;
};
-define NumberOfLights = 8;
+public define NumberOfLights = 8;
// Painter's algorithm
void FontExtent(Font font, const char * text, int len, int * width, int * height)
{
- int overHang;
+ int overHang = 0;
FontExtent2(font, text, len, width, height, 0, null, &overHang);
if(width) *width += overHang;
}
result = displaySystem && displaySystem.Lock();
if(result && render)
{
+#if !defined(__EMSCRIPTEN__)
mutex.Wait();
+#endif
if(!current)
result = displaySystem.driver.Lock(this);
*/
if(!current && displaySystem)
displaySystem.driver.Unlock(this);
+#if !defined(__EMSCRIPTEN__)
mutex.Release();
+#endif
}
if(displaySystem)
displaySystem.Unlock();
// --- Lights ---
void SetLight(int id, Light light)
{
+ if(!display3D)
+ {
+ display3D = Display3D { };
+ }
displaySystem.driver.SetLight(this, id, light);
}
if(!display3D.selection && displaySystem.driver.PushMatrix)
displaySystem.driver.PushMatrix(this);
+#if ENABLE_GL_FFP
+ if(object.mesh.tangents && object.mesh.normals && object.flags.computeLightVectors)
+ {
+ Mesh mesh = object.mesh;
+ if(!glCaps_shaders)
+ {
+ int count = mesh.nVertices;
+ Vector3Df * normals = mesh.normals;
+ Vector3Df * vertices = mesh.vertices;
+ ColorRGB * lightVectors;
+ Vector3Df * tangents = mesh.tangents;
+ int i;
+ float * l = display3D.light0Pos;
+ Vector3Df light { l[0], l[1], l[2] };
+ Matrix o = object.matrix;
+ Matrix t, inv = camera.viewMatrix;
+ Vector3D ot { };
+ Vector3D cPos = camera.cPosition;
+ Vector3D pos;
+ bool positional = l[3] ? true : false;
+
+ inv.Scale(1.0/nearPlane, -1.0/nearPlane,-1.0/nearPlane);
+
+ pos.MultMatrix(cPos, camera.viewMatrix);
+
+ ot.x = o.m[3][0] + pos.x;
+ ot.y = o.m[3][1] + pos.y;
+ ot.z = o.m[3][2] + pos.z;
+ o.m[3][0] = 0;
+ o.m[3][1] = 0;
+ o.m[3][2] = 0;
+ t.Multiply(o, inv);
+ inv = t;
+ t.Transpose(inv);
+ inv.Inverse(t);
+
+ mesh.Allocate({ lightVectors = true }, mesh.nVertices, displaySystem);
+ mesh.Lock({ lightVectors = true });
+ lightVectors = mesh.lightVectors;
+ for(i = 0; i < count; i++)
+ {
+ Vector3Df tangent1 = tangents[i*2 + 0];
+ Vector3Df tangent2 = tangents[i*2 + 1];
+ Vector3Df normal = normals[i];
+ Vector3Df tTangent1, tTangent2, tNormal;
+
+ tTangent1.MultMatrix(tangent1, inv);
+ tTangent2.MultMatrix(tangent2, inv);
+ tNormal .MultMatrix(normal, inv);
+
+ tTangent1.Normalize(tTangent1);
+ tTangent2.Normalize(tTangent2);
+ tNormal .Normalize(tNormal);
+
+ {
+ Matrix tbn
+ { {
+ tTangent1.x, tTangent2.x, tNormal.x, 0,
+ tTangent1.y, tTangent2.y, tNormal.y, 0,
+ tTangent1.z, tTangent2.z, tNormal.z, 1
+ } };
+ Vector3Df n;
+ if(positional)
+ {
+ Vector3Df tPos = vertices[i];
+ tPos.x += ot.x, tPos.y += ot.y, tPos.z += ot.z;
+
+ // Subtract vertex from light for positional lights
+ light.x = l[0] - tPos.x;
+ light.y = l[1] + tPos.y;
+ light.z = l[2] - tPos.z;
+ }
+ n.MultMatrix(light, tbn);
+ if(positional)
+ n.Normalize(n);
+ lightVectors[i] = { n.x / 2 + 0.5f, n.y / 2 + 0.5f, n.z / 2 + 0.5f };
+ }
+ }
+ mesh.Unlock({ lightVectors = true });
+
+ // Create normalization cube map
+ /*
+ if(!mesh.normMap)
+ mesh.normMap = { };
+ {
+ int w = 256, h = 256, d = 256;
+ Vector3Df min = mesh.min, max = mesh.max;
+ Vector3Df delta
+ {
+ (max.x - min.x) / w,
+ (max.y - min.y) / h,
+ (max.z - min.z) / d
+ };
+ int i;
+ for(i = 0; i < 6; i++)
+ {
+ Bitmap face = i > 0 ? { } : mesh.normMap;
+ int x, y;
+ ColorAlpha * p;
+ face.Free();
+ face.Allocate(null, w, h, 0, pixelFormat888, false);
+ face.driverData = mesh.normMap.driverData;
+ p = (ColorAlpha *)face.picture;
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++, p++)
+ {
+ Vector3Df v { min.x + x * delta.x, min.y + y * delta.y, min.z };
+ v.Normalize(v);
+ *p = ColorAlpha { 255, {
+ (byte)((v.x / 2.0 + 0.5) * 255),
+ (byte)((v.y / 2.0 + 0.5) * 255),
+ (byte)((v.z / 2.0 + 0.5) * 255) } };
+ }
+ }
+ displaySystem.driver.MakeDDBitmap(displaySystem, face, true, (i + 1));
+ if(i > 0)
+ {
+ face.driverData = 0;
+ delete face;
+ }
+ }
+ }
+ */
+ }
+ else
+ mesh.Free({ lightVectors = true });
+ }
+#endif
+
SetTransform(object.matrix, object.flags.viewSpace);
if(display3D.selection)
{
set
{
glCapabilities = value;
- if(driverData)
+ if(driverData && displaySystem.driver == class(OpenGLDisplayDriver))
{
OGLDisplay oglDisplay = driverData;
if(!oglDisplay.originalCapabilities.fixedFunction)
value.shaders = true;
if(!oglDisplay.originalCapabilities.shaders)
value.fixedFunction = true;
+ // Disable things that don't work with shaders
+ if(value.shaders)
+ {
+ value.fixedFunction = false;
+ value.legacy = false;
+ value.immediate = false;
+ }
oglDisplay.capabilities = oglDisplay.originalCapabilities & value;
+
Lock(true);
- OpenGLDisplayDriver::initialDisplaySetup(this);
+ OpenGLDisplayDriver::initialDisplaySetup(this, true, false);
Unlock();
}
}
DisplaySystem displaySystem;
void * window;
+#if !defined(__EMSCRIPTEN__)
Mutex mutex { };
+#endif
int current;
#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
Line rayView, rayWorld, rayLocal;
Vector3D rayIntersect;
+ float light0Pos[4];
~Display3D()
{
}
return best;
}
+
+// had to move this here due to compiler ordering issue for "get property" symbol
+subclass(DisplayDriver) GetDisplayDriver(const char * driverName)
+{
+ if(driverName)
+ {
+ OldLink link;
+ for(link = class(DisplayDriver).derivatives.first; link; link = link.next)
+ {
+ subclass(DisplayDriver) displayDriver = link.data;
+ if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName))
+ return displayDriver;
+ }
+ }
+ return null;
+}
+
+DisplaySystem GetDisplaySystem(const char * driverName)
+{
+ subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
+ return displayDriver ? displayDriver.displaySystem : null;
+}