Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,2 @@
DisableFormat: true
SortIncludes: false

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
#pragma once
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/textureunit.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef KINC_KONG
int Kinc_G4_Internal_TextureAddressingU(uint32_t unit);
int Kinc_G4_Internal_TextureAddressingV(uint32_t unit);
#else
int Kinc_G4_Internal_TextureAddressingU(kinc_g4_texture_unit_t unit);
int Kinc_G4_Internal_TextureAddressingV(kinc_g4_texture_unit_t unit);
#endif
int Kinc_G4_Internal_StencilFunc(kinc_g4_compare_mode_t mode);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,221 @@
#ifdef KINC_WINDOWS
#include "OpenGLWindow.h"
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/indexbuffer.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/rendertarget.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics4/vertexbuffer.h>
#include <kinc/system.h>
#include <kinc/window.h>
#include <kinc/backend/Windows.h>
#include "ogl.h"
#include <GL/wglew.h>
Kinc_Internal_OpenGLWindow Kinc_Internal_windows[10] = {0};
static kinc_g4_vertex_buffer_t windowVertexBuffer;
static kinc_g4_index_buffer_t windowIndexBuffer;
static kinc_g4_pipeline_t windowPipeline;
static bool initialized = false;
static kinc_g4_shader_t windowVertexShader;
static kinc_g4_shader_t windowFragmentShader;
static bool glewInitialized = false;
void Kinc_Internal_initWindowsGLContext(int window, int depthBufferBits, int stencilBufferBits) {
HWND windowHandle = kinc_windows_window_handle(window);
Kinc_Internal_windows[window].depthBufferBits = depthBufferBits;
#ifndef VR_RIFT
PIXELFORMATDESCRIPTOR pfd = {sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
(BYTE)depthBufferBits,
(BYTE)stencilBufferBits,
0,
PFD_MAIN_PLANE,
0,
0,
0,
0};
Kinc_Internal_windows[window].deviceContext = GetDC(windowHandle);
GLuint pixelFormat = ChoosePixelFormat(Kinc_Internal_windows[window].deviceContext, &pfd);
SetPixelFormat(Kinc_Internal_windows[window].deviceContext, pixelFormat, &pfd);
HGLRC tempGlContext = wglCreateContext(Kinc_Internal_windows[window].deviceContext);
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, tempGlContext);
if (!glewInitialized) {
glewInit();
glewInitialized = true;
}
if (wglewIsSupported("WGL_ARB_create_context") == 1) {
int attributes[] = {WGL_CONTEXT_MAJOR_VERSION_ARB,
4,
WGL_CONTEXT_MINOR_VERSION_ARB,
2,
WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0};
Kinc_Internal_windows[window].glContext =
wglCreateContextAttribsARB(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[0].glContext, attributes);
glCheckErrors();
wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempGlContext);
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[window].glContext);
glCheckErrors();
}
else {
Kinc_Internal_windows[window].glContext = tempGlContext;
}
#else
deviceContexts[window] = GetDC(windowHandle);
glContexts[window] = wglGetCurrentContext();
if (!glewInitialized) {
glewInit();
glewInitialized = true;
}
#endif
if (window != 0) {
wglShareLists(Kinc_Internal_windows[0].glContext, Kinc_Internal_windows[window].glContext);
wglMakeCurrent(Kinc_Internal_windows[0].deviceContext, Kinc_Internal_windows[0].glContext);
kinc_g4_render_target_init(&Kinc_Internal_windows[window].renderTarget, kinc_windows_manual_width(window), kinc_windows_manual_height(window),
KINC_G4_RENDER_TARGET_FORMAT_32BIT, depthBufferBits, 0);
if (!initialized) {
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[window].glContext);
kinc_g4_vertex_structure_t structure;
kinc_g4_vertex_structure_init(&structure);
kinc_g4_vertex_structure_add(&structure, "pos", KINC_G4_VERTEX_DATA_F32_2X);
kinc_g4_vertex_buffer_init(&windowVertexBuffer, 4, &structure, KINC_G4_USAGE_STATIC, 0);
float *vertices = kinc_g4_vertex_buffer_lock_all(&windowVertexBuffer);
vertices[0] = -1.0f;
vertices[1] = -1.0f;
vertices[2] = -1.0f;
vertices[3] = 1.0f;
vertices[4] = 1.0f;
vertices[5] = 1.0f;
vertices[6] = 1.0f;
vertices[7] = -1.0f;
kinc_g4_vertex_buffer_unlock_all(&windowVertexBuffer);
kinc_g4_index_buffer_init(&windowIndexBuffer, 6, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC);
int *indices = kinc_g4_index_buffer_lock_all(&windowIndexBuffer);
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 0;
indices[4] = 2;
indices[5] = 3;
kinc_g4_index_buffer_unlock_all(&windowIndexBuffer);
char *vertex_shader = "#version 450\n"
"in vec2 pos;\n"
"out vec2 texCoord;\n"
"void main() {\n"
"gl_Position = vec4(pos, 0.5, 1.0);\n"
"texCoord = (pos + 1.0) / 2.0;\n"
"}\n";
kinc_g4_shader_init(&windowVertexShader, vertex_shader, strlen(vertex_shader), KINC_G4_SHADER_TYPE_VERTEX);
char *fragment_shader = "#version 450\n"
"uniform sampler2D tex;\n"
"in vec2 texCoord;\n"
"out vec4 frag;\n"
"void main() {\n"
"frag = texture(tex, texCoord);\n"
"}\n";
kinc_g4_shader_init(&windowFragmentShader, fragment_shader, strlen(fragment_shader), KINC_G4_SHADER_TYPE_FRAGMENT);
kinc_g4_pipeline_init(&windowPipeline);
windowPipeline.input_layout[0] = &structure;
windowPipeline.input_layout[1] = NULL;
windowPipeline.vertex_shader = &windowVertexShader;
windowPipeline.fragment_shader = &windowFragmentShader;
kinc_g4_pipeline_compile(&windowPipeline);
wglMakeCurrent(Kinc_Internal_windows[0].deviceContext, Kinc_Internal_windows[0].glContext);
initialized = true;
}
}
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[window].glContext);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &Kinc_Internal_windows[window].framebuffer);
glGenVertexArrays(1, &Kinc_Internal_windows[window].vertexArray);
glCheckErrors();
wglMakeCurrent(Kinc_Internal_windows[0].deviceContext, Kinc_Internal_windows[0].glContext);
glBindVertexArray(Kinc_Internal_windows[0].vertexArray);
glCheckErrors();
}
void Kinc_Internal_blitWindowContent(int window) {
glBindFramebuffer(GL_FRAMEBUFFER, Kinc_Internal_windows[window].framebuffer);
kinc_g4_clear(KINC_G4_CLEAR_COLOR, 0xff00ffff, 0.0f, 0);
kinc_g4_set_pipeline(&windowPipeline);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Kinc_Internal_windows[window].renderTarget.impl._texture);
kinc_g4_set_index_buffer(&windowIndexBuffer);
glBindVertexArray(Kinc_Internal_windows[window].vertexArray);
glCheckErrors();
kinc_g4_vertex_buffer_t *vertexBuffers[1] = {&windowVertexBuffer};
kinc_g4_set_vertex_buffers(vertexBuffers, 1);
glViewport(0, 0, kinc_window_width(window), kinc_window_height(window));
kinc_g4_draw_indexed_vertices();
glCheckErrors();
glBindVertexArray(Kinc_Internal_windows[0].vertexArray);
glCheckErrors();
}
void Kinc_Internal_resizeWindowRenderTarget(int window, int width, int height) {
if (window != 0) {
kinc_g4_render_target_destroy(&Kinc_Internal_windows[window].renderTarget);
kinc_g4_render_target_init(&Kinc_Internal_windows[window].renderTarget, width, height, KINC_G4_RENDER_TARGET_FORMAT_32BIT,
Kinc_Internal_windows[window].depthBufferBits, 0);
}
}
void Kinc_Internal_setWindowRenderTarget(int window) {
if (window == 0) {
glBindFramebuffer(GL_FRAMEBUFFER, Kinc_Internal_windows[window].framebuffer);
}
else {
kinc_g4_render_target_t *renderTargets[1] = {&Kinc_Internal_windows[window].renderTarget};
kinc_g4_set_render_targets(renderTargets, 1);
}
}
#endif

View File

@ -0,0 +1,34 @@
#pragma once
#ifdef KINC_WINDOWS
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#ifdef __cplusplus
extern "C" {
#endif
struct kinc_g4_render_target;
typedef struct {
HDC deviceContext;
HGLRC glContext;
int depthBufferBits;
int framebuffer;
unsigned vertexArray;
struct kinc_g4_render_target renderTarget;
} Kinc_Internal_OpenGLWindow;
extern Kinc_Internal_OpenGLWindow Kinc_Internal_windows[10];
void Kinc_Internal_initWindowsGLContext(int window, int depthBufferBits, int stencilBufferBits);
void Kinc_Internal_blitWindowContent(int window);
void Kinc_Internal_setWindowRenderTarget(int window);
void Kinc_Internal_resizeWindowRenderTarget(int window, int width, int height);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,55 @@
#include "ogl.h"
#include <kinc/graphics4/compute.h>
#if defined(KINC_WINDOWS) || (defined(KINC_LINUX) && defined(GL_VERSION_4_3)) || (defined(KINC_ANDROID) && defined(GL_ES_VERSION_3_1))
#define HAS_COMPUTE
#endif
kinc_shader_storage_buffer_t *currentStorageBuffer = NULL;
static void unset(kinc_shader_storage_buffer_t *buffer) {
if (currentStorageBuffer == buffer)
currentStorageBuffer = NULL;
}
void kinc_shader_storage_buffer_init(kinc_shader_storage_buffer_t *buffer, int indexCount, kinc_g4_vertex_data_t type) {
buffer->impl.myCount = indexCount;
buffer->impl.myStride = 0;
buffer->impl.myStride += kinc_g4_vertex_data_size(type);
#ifdef HAS_COMPUTE
glGenBuffers(1, &buffer->impl.bufferId);
glCheckErrors();
#endif
buffer->impl.data = (int *)malloc(sizeof(int) * indexCount);
}
void kinc_shader_storage_buffer_destroy(kinc_shader_storage_buffer_t *buffer) {
unset(buffer);
free(buffer->impl.data);
}
int *kinc_shader_storage_buffer_lock(kinc_shader_storage_buffer_t *buffer) {
return buffer->impl.data;
}
void kinc_shader_storage_buffer_unlock(kinc_shader_storage_buffer_t *buffer) {
#ifdef HAS_COMPUTE
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer->impl.bufferId);
glCheckErrors();
glBufferData(GL_SHADER_STORAGE_BUFFER, buffer->impl.myCount * buffer->impl.myStride, buffer->impl.data, GL_STATIC_DRAW);
glCheckErrors();
#endif
}
void kinc_shader_storage_buffer_internal_set(kinc_shader_storage_buffer_t *buffer) {
currentStorageBuffer = buffer;
#ifdef HAS_COMPUTE
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer->impl.bufferId);
glCheckErrors();
#endif
}
int kinc_shader_storage_buffer_count(kinc_shader_storage_buffer_t *buffer) {
return buffer->impl.myCount;
}

View File

@ -0,0 +1,11 @@
#pragma once
typedef struct {
// ShaderStorageBufferImpl(int count, Graphics4::VertexData type);
// void unset();
int *data;
int myCount;
int myStride;
unsigned bufferId;
// static ShaderStorageBuffer* current;
} kinc_compute_shader_storage_buffer_impl_t;

View File

@ -0,0 +1,634 @@
#ifdef KINC_OCULUS
#include <Kinc/vr/vrinterface.h>
#include <Kinc/graphics4/graphics.h>
#include <Kinc/graphics4/rendertarget.h>
#include <Kore/Log.h>
#include "Extras/OVR_Math.h"
#include "GL/CAPI_GLE.h"
#include "OVR_CAPI_GL.h"
#include <assert.h>
using namespace Kore;
namespace {
kinc_vr_sensor_state_t sensorStates[2];
}
struct TextureBuffer {
ovrSession Session;
ovrTextureSwapChain TextureChain;
OVR::Sizei texSize;
kinc_g4_render_target_t OVRRenderTarget;
bool render_target_initialized;
TextureBuffer(ovrSession session, bool displayableOnHmd, OVR::Sizei size, int mipLevels, unsigned char *data, int sampleCount)
: Session(session), TextureChain(nullptr), texSize(size), render_target_initialized(false) {
UNREFERENCED_PARAMETER(sampleCount);
assert(sampleCount <= 1); // The code doesn't currently handle MSAA textures.
if (displayableOnHmd) {
// This texture isn't necessarily going to be a rendertarget, but it usually is.
assert(session); // No HMD? A little odd.
assert(sampleCount == 1); // ovr_CreateSwapTextureSetD3D11 doesn't support MSAA.
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Width = size.w;
desc.Height = size.h;
desc.MipLevels = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.SampleCount = 1;
desc.StaticImage = ovrFalse;
ovrResult result = ovr_CreateTextureSwapChainGL(Session, &desc, &TextureChain);
int length = 0;
ovr_GetTextureSwapChainLength(session, TextureChain, &length);
if (OVR_SUCCESS(result)) {
for (int i = 0; i < length; ++i) {
GLuint chainTexId;
ovr_GetTextureSwapChainBufferGL(Session, TextureChain, i, &chainTexId);
glBindTexture(GL_TEXTURE_2D, chainTexId);
kinc_g4_render_target_init(&OVRRenderTarget, texSize.w, texSize.h, 0, false, KINC_G4_RENDER_TARGET_FORMAT_32BIT, 0, 0);
render_target_initialized = true;
}
}
}
if (mipLevels > 1) {
glGenerateMipmap(GL_TEXTURE_2D);
}
}
~TextureBuffer() {
if (TextureChain) {
ovr_DestroyTextureSwapChain(Session, TextureChain);
TextureChain = nullptr;
}
if (render_target_initialized) {
kinc_g4_render_target_destroy(&OVRRenderTarget);
}
}
OVR::Sizei GetSize() const {
return texSize;
}
void SetAndClearRenderSurface() {
GLuint curTexId;
int curIndex;
ovr_GetTextureSwapChainCurrentIndex(Session, TextureChain, &curIndex);
ovr_GetTextureSwapChainBufferGL(Session, TextureChain, curIndex, &curTexId);
if (render_target_initialized) {
kinc_g4_render_target_t *renderTargets[1] = {&OVRRenderTarget};
kinc_g4_set_render_targets(renderTargets, 1);
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, OVRRenderTarget.impl._depthTexture, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glEnable(GL_FRAMEBUFFER_SRGB); // TODO: too bright
}
void UnsetRenderSurface() {
glBindFramebuffer(GL_FRAMEBUFFER, OVRRenderTarget.impl._framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
}
void Commit() {
if (TextureChain) {
ovr_CommitTextureSwapChain(Session, TextureChain);
}
}
};
//-------------------------------------------------------------------------------------------
struct OGL {
HWND Window;
HDC hDC;
HGLRC WglContext;
OVR::GLEContext GLEContext;
bool Running;
bool Key[256];
int WinSizeW;
int WinSizeH;
HINSTANCE hInstance;
OGL() : Window(nullptr), hDC(nullptr), WglContext(nullptr), GLEContext(), Running(false), WinSizeW(0), WinSizeH(0), hInstance(nullptr) {
// Clear input
for (int i = 0; i < sizeof(Key) / sizeof(Key[0]); ++i)
Key[i] = false;
}
~OGL() {
ReleaseDevice();
CloseWindow();
}
bool InitWindow(HINSTANCE hInst, const char *title, const char *windowClassName) {
hInstance = hInst;
Running = true;
// Adjust the window size and show at InitDevice time
wchar_t wchTitle[256];
MultiByteToWideChar(CP_ACP, 0, title, -1, wchTitle, 256);
wchar_t wchClassName[256];
MultiByteToWideChar(CP_ACP, 0, windowClassName, -1, wchClassName, 256);
Window = CreateWindowW(wchClassName, wchTitle, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, hInst, 0);
if (!Window)
return false;
SetWindowLongPtr(Window, 0, LONG_PTR(this));
hDC = GetDC(Window);
return true;
}
void CloseWindow() {
if (Window) {
if (hDC) {
ReleaseDC(Window, hDC);
hDC = nullptr;
}
Window = nullptr;
}
}
// Note: currently there is no way to get GL to use the passed pLuid
bool InitDevice(int vpW, int vpH, const LUID * /*pLuid*/, bool windowed = true) {
UNREFERENCED_PARAMETER(windowed);
WinSizeW = vpW;
WinSizeH = vpH;
RECT size = {0, 0, vpW, vpH};
AdjustWindowRect(&size, WS_OVERLAPPEDWINDOW, false);
const UINT flags = SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW;
if (!SetWindowPos(Window, nullptr, 0, 0, size.right - size.left, size.bottom - size.top, flags))
return false;
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBFunc = nullptr;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARBFunc = nullptr;
{
// First create a context for the purpose of getting access to wglChoosePixelFormatARB / wglCreateContextAttribsARB.
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
pfd.cColorBits = 32;
pfd.cDepthBits = 16;
int pf = ChoosePixelFormat(hDC, &pfd);
if (!pf) {
log(Warning, "Failed to choose pixel format.");
ReleaseDC(Window, hDC);
return false;
}
if (!SetPixelFormat(hDC, pf, &pfd)) {
log(Warning, "Failed to set pixel format.");
ReleaseDC(Window, hDC);
return false;
}
HGLRC context = wglCreateContext(hDC);
if (!context) {
log(Warning, "wglCreateContextfailed.");
ReleaseDC(Window, hDC);
return false;
}
if (!wglMakeCurrent(hDC, context)) {
log(Warning, "wglMakeCurrent failed.");
wglDeleteContext(context);
ReleaseDC(Window, hDC);
return false;
}
wglChoosePixelFormatARBFunc = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
wglCreateContextAttribsARBFunc = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
assert(wglChoosePixelFormatARBFunc && wglCreateContextAttribsARBFunc);
wglDeleteContext(context);
}
// Now create the real context that we will be using.
int iAttributes[] = {// WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB,
GL_TRUE,
WGL_COLOR_BITS_ARB,
32,
WGL_DEPTH_BITS_ARB,
16,
WGL_DOUBLE_BUFFER_ARB,
GL_TRUE,
WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB,
GL_TRUE,
0,
0};
float fAttributes[] = {0, 0};
int pf = 0;
UINT numFormats = 0;
if (!wglChoosePixelFormatARBFunc(hDC, iAttributes, fAttributes, 1, &pf, &numFormats)) {
log(Warning, "wglChoosePixelFormatARBFunc failed.");
ReleaseDC(Window, hDC);
return false;
}
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
if (!SetPixelFormat(hDC, pf, &pfd)) {
log(Warning, "SetPixelFormat failed.");
ReleaseDC(Window, hDC);
return false;
}
GLint attribs[16];
int attribCount = 0;
attribs[attribCount] = 0;
WglContext = wglCreateContextAttribsARBFunc(hDC, 0, attribs);
if (!wglMakeCurrent(hDC, WglContext)) {
log(Warning, "wglMakeCurrent failed.");
wglDeleteContext(WglContext);
ReleaseDC(Window, hDC);
return false;
}
OVR::GLEContext::SetCurrentContext(&GLEContext);
GLEContext.Init();
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CW);
glEnable(GL_CULL_FACE);
return true;
}
void ReleaseDevice() {
if (WglContext) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(WglContext);
WglContext = nullptr;
}
GLEContext.Shutdown();
}
};
namespace {
TextureBuffer *eyeRenderTexture[2] = {nullptr, nullptr};
ovrMirrorTexture mirrorTexture = nullptr;
uint mirrorFBO = 0;
long long frameIndex = 0;
bool isVisible = true;
ovrSession session;
ovrHmdDesc hmdDesc;
ovrPosef EyeRenderPose[2];
double sensorSampleTime;
OGL Platform;
void done() {
if (mirrorFBO)
glDeleteFramebuffers(1, &mirrorFBO);
if (mirrorTexture)
ovr_DestroyMirrorTexture(session, mirrorTexture);
for (int eye = 0; eye < 2; ++eye) {
delete eyeRenderTexture[eye];
}
Platform.ReleaseDevice();
ovr_Destroy(session);
}
void createOculusTexture() {
// Make eye render buffers
for (int eye = 0; eye < 2; ++eye) {
ovrSizei idealTextureSize = ovr_GetFovTextureSize(session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1);
eyeRenderTexture[eye] = new TextureBuffer(session, true, idealTextureSize, 1, NULL, 1);
if (!eyeRenderTexture[eye]->TextureChain) {
log(Info, "Failed to create texture.");
done();
}
}
ovrMirrorTextureDesc desc;
memset(&desc, 0, sizeof(desc));
desc.Width = Platform.WinSizeW;
desc.Height = Platform.WinSizeH;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
// Create mirror texture and an FBO used to copy mirror texture to back buffer
ovrResult result = ovr_CreateMirrorTextureWithOptionsGL(session, &desc, &mirrorTexture);
if (!OVR_SUCCESS(result)) {
log(Info, "Failed to create mirror texture.");
done();
}
// Configure the mirror read buffer
GLuint texId;
ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId);
glGenFramebuffers(1, &mirrorFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
}
void *kinc_vr_interface_init(void *hinst, const char *title, const char *windowClassName) {
ovrInitParams initParams = {ovrInit_RequestVersion, OVR_MINOR_VERSION, NULL, 0, 0};
ovrResult result = ovr_Initialize(&initParams);
if (!OVR_SUCCESS(result)) {
log(Warning, "Failed to initialize libOVR.");
return (0);
}
if (!Platform.InitWindow((HINSTANCE)hinst, title, windowClassName)) {
log(Warning, "Failed to open window.");
return (0);
}
ovrGraphicsLuid luid;
result = ovr_Create(&session, &luid);
if (!OVR_SUCCESS(result)) {
log(Info, "HMD not connected.");
return false; // TODO: retry
}
hmdDesc = ovr_GetHmdDesc(session);
// Setup Window and Graphics
// Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution
ovrSizei windowSize = {hmdDesc.Resolution.w / 2, hmdDesc.Resolution.h / 2};
if (!Platform.InitDevice(windowSize.w, windowSize.h, reinterpret_cast<LUID *>(&luid))) {
log(Info, "Failed to init device.");
done();
}
// FloorLevel will give tracking poses where the floor height is 0
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
// Return window
return Platform.Window;
}
void kinc_vr_interface_begin() {
// Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyeOffset) may change at runtime.
ovrEyeRenderDesc eyeRenderDesc[2];
eyeRenderDesc[0] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[0]);
eyeRenderDesc[1] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[1]);
// Get both eye poses simultaneously, with IPD offset already included.
ovrPosef HmdToEyePose[2] = {eyeRenderDesc[0].HmdToEyePose, eyeRenderDesc[1].HmdToEyePose};
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyePose, EyeRenderPose, &sensorSampleTime);
}
void kinc_vr_interface_begin_render(int eye) {
if (eyeRenderTexture[0] == nullptr || eyeRenderTexture[1] == nullptr)
createOculusTexture();
// Switch to eye render target
eyeRenderTexture[eye]->SetAndClearRenderSurface();
}
void kinc_vr_interface_end_render(int eye) {
// Avoids an error when calling SetAndClearRenderSurface during next iteration.
eyeRenderTexture[eye]->UnsetRenderSurface();
// Commit changes to the textures so they get picked up frame
eyeRenderTexture[eye]->Commit();
}
namespace {
kinc_matrix4x4_t convert(OVR::Matrix4f &m) {
kinc_matrix4x4_t mat;
kinc_matrix4x4_set(&mat, 0, 0, m.M[0][0]);
kinc_matrix4x4_set(&mat, 0, 1, m.M[0][1]);
kinc_matrix4x4_set(&mat, 0, 2, m.M[0][2]);
kinc_matrix4x4_set(&mat, 0, 3, m.M[0][3]);
kinc_matrix4x4_set(&mat, 1, 0, m.M[1][0]);
kinc_matrix4x4_set(&mat, 1, 1, m.M[1][1]);
kinc_matrix4x4_set(&mat, 1, 2, m.M[1][2]);
kinc_matrix4x4_set(&mat, 1, 3, m.M[1][3]);
kinc_matrix4x4_set(&mat, 2, 0, m.M[2][0]);
kinc_matrix4x4_set(&mat, 2, 1, m.M[2][1]);
kinc_matrix4x4_set(&mat, 2, 2, m.M[2][2]);
kinc_matrix4x4_set(&mat, 2, 3, m.M[2][3]);
kinc_matrix4x4_set(&mat, 3, 0, m.M[3][0]);
kinc_matrix4x4_set(&mat, 3, 1, m.M[3][1]);
kinc_matrix4x4_set(&mat, 3, 2, m.M[3][2]);
kinc_matrix4x4_set(&mat, 3, 3, m.M[3][3]);
return mat;
}
// Vector<float, 3> vectorConvert(const OVR::Vector3f& v) {
// return { v.x, v.y, v.z };
// }
// OVR::Vector3f vectorConvert(const Vector<float, 3>& v) {
// return { v.x(), v.y(), v.z() };
// }
}
/*SensorState VrInterface::getSensorState(int eye, Kore::Vector<float, 3>& headPosition) {
VrPoseState poseState;
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
poseState.vrPose.orientation = Quaternion(orientation.x, orientation.y, orientation.z, orientation.w);
ovrVector3f pos = EyeRenderPose[eye].Position;
poseState.vrPose.position = vec3(pos.x, pos.y, pos.z);
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
poseState.vrPose.left = fov.LeftTan;
poseState.vrPose.right = fov.RightTan;
poseState.vrPose.bottom = fov.DownTan;
poseState.vrPose.top = fov.UpTan;
// Get view and projection matrices
OVR::Matrix4f finalRollPitchYaw = OVR::Matrix4f(EyeRenderPose[eye].Orientation);
OVR::Vector3f finalUp = finalRollPitchYaw.Transform(OVR::Vector3f(0, 1, 0));
OVR::Vector3f finalForward = finalRollPitchYaw.Transform(OVR::Vector3f(0, 0, -1));
Kore::Vector<float, 3> right = vectorConvert(finalForward).cross(vectorConvert(finalUp)).normalize() * 0.01f;
OVR::Vector3f shiftedEyePos;
if (eye == 0) {
shiftedEyePos = vectorConvert(headPosition - right);
} else {
shiftedEyePos = vectorConvert(headPosition + right);
}
OVR::Matrix4f view = OVR::Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + finalForward, finalUp);
OVR::Matrix4f proj = ovrMatrix4f_Projection(hmdDesc.MaxEyeFov[eye], 0.2f, 1000.0f, ovrProjection_None);
poseState.vrPose.eye = convert(view);
poseState.vrPose.projection = convert(proj);
ovrSessionStatus sessionStatus;
ovr_GetSessionStatus(session, &sessionStatus);
if (sessionStatus.IsVisible) poseState.isVisible = true;
else poseState.isVisible = false;
if (sessionStatus.HmdPresent) poseState.hmdPresenting = true;
else poseState.hmdPresenting = false;
if (sessionStatus.HmdMounted) poseState.hmdMounted = true;
else poseState.hmdMounted = false;
if (sessionStatus.DisplayLost) poseState.displayLost = true;
else poseState.displayLost = false;
if (sessionStatus.ShouldQuit) poseState.shouldQuit = true;
else poseState.shouldQuit = false;
if (sessionStatus.ShouldRecenter) poseState.shouldRecenter = true;
else poseState.shouldRecenter = false;
sensorStates[eye].pose = poseState;
return sensorStates[eye];
}*/
kinc_vr_sensor_state_t kinc_vr_interface_get_sensor_state(int eye) {
kinc_vr_pose_state_t poseState;
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
poseState.vrPose.orientation.x = orientation.x;
poseState.vrPose.orientation.y = orientation.y;
poseState.vrPose.orientation.z = orientation.z;
poseState.vrPose.orientation.w = orientation.w;
ovrVector3f pos = EyeRenderPose[eye].Position;
poseState.vrPose.position.x = pos.x;
poseState.vrPose.position.y = pos.y;
poseState.vrPose.position.z = pos.z;
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
poseState.vrPose.left = fov.LeftTan;
poseState.vrPose.right = fov.RightTan;
poseState.vrPose.bottom = fov.DownTan;
poseState.vrPose.top = fov.UpTan;
// Get view and projection matrices
OVR::Matrix4f finalRollPitchYaw = OVR::Matrix4f(EyeRenderPose[eye].Orientation);
OVR::Vector3f finalUp = finalRollPitchYaw.Transform(OVR::Vector3f(0, 1, 0));
OVR::Vector3f finalForward = finalRollPitchYaw.Transform(OVR::Vector3f(0, 0, -1));
OVR::Vector3f shiftedEyePos = EyeRenderPose[eye].Position;
OVR::Matrix4f view = OVR::Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + finalForward, finalUp);
OVR::Matrix4f proj = ovrMatrix4f_Projection(hmdDesc.DefaultEyeFov[eye], 0.2f, 1000.0f, ovrProjection_None);
poseState.vrPose.eye = convert(view);
poseState.vrPose.projection = convert(proj);
ovrSessionStatus sessionStatus;
ovr_GetSessionStatus(session, &sessionStatus);
if (sessionStatus.IsVisible)
poseState.isVisible = true;
else
poseState.isVisible = false;
if (sessionStatus.HmdPresent)
poseState.hmdPresenting = true;
else
poseState.hmdPresenting = false;
if (sessionStatus.HmdMounted)
poseState.hmdMounted = true;
else
poseState.hmdMounted = false;
if (sessionStatus.DisplayLost)
poseState.displayLost = true;
else
poseState.displayLost = false;
if (sessionStatus.ShouldQuit)
poseState.shouldQuit = true;
else
poseState.shouldQuit = false;
if (sessionStatus.ShouldRecenter)
poseState.shouldRecenter = true;
else
poseState.shouldRecenter = false;
sensorStates[eye].pose = poseState;
return sensorStates[eye];
}
kinc_vr_pose_state_t kinc_vr_interface_get_controller(int index) {
kinc_vr_pose_state_t todo;
return todo;
}
void kinc_vr_interface_warp_swap() {
// Initialize our single full screen Fov layer.
ovrLayerEyeFov ld;
ld.Header.Type = ovrLayerType_EyeFov;
ld.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; // Because OpenGL.
if (isVisible) {
for (int eye = 0; eye < 2; ++eye) {
ld.ColorTexture[eye] = eyeRenderTexture[eye]->TextureChain;
ld.Viewport[eye] = OVR::Recti(eyeRenderTexture[eye]->GetSize());
ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
ld.RenderPose[eye] = EyeRenderPose[eye];
ld.SensorSampleTime = sensorSampleTime;
}
}
ovrLayerHeader *layers = &ld.Header;
ovrResult result = ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);
if (!OVR_SUCCESS(result)) {
isVisible = false;
}
else {
isVisible = true;
}
frameIndex++;
// Blit mirror texture to back buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
GLint w = Platform.WinSizeW;
GLint h = Platform.WinSizeH;
glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
void kinc_vr_interface_update_tracking_origin(kinc_tracking_origin_t origin) {
switch (origin) {
case KINC_TRACKING_ORIGIN_STAND:
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
break;
case KINC_TRACKING_ORIGIN_SIT:
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel);
break;
default:
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
break;
}
}
void kinc_vr_interface_reset_hmd_pose() {
ovr_RecenterTrackingOrigin(session);
}
void kinc_vr_interface_ovr_shutdown() {
ovr_Shutdown();
}
#endif

View File

@ -0,0 +1,202 @@
#include <kinc/graphics4/compute.h>
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/rendertarget.h>
#include <kinc/graphics4/texture.h>
#include <kinc/image.h>
#include <kinc/log.h>
#include <kinc/math/core.h>
#include <kinc/backend/graphics4/ogl.h>
#include <stdio.h>
#include <string.h>
#if defined(KINC_WINDOWS) || (defined(KINC_LINUX) && defined(GL_VERSION_4_3)) || (defined(KINC_ANDROID) && defined(GL_ES_VERSION_3_1))
#define HAS_COMPUTE
bool kinc_internal_gl_has_compute = true;
#else
bool kinc_internal_gl_has_compute = false;
#endif
#ifdef HAS_COMPUTE
static int convertInternalImageFormat(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA128:
return GL_RGBA32F;
case KINC_IMAGE_FORMAT_RGBA64:
return GL_RGBA16F;
case KINC_IMAGE_FORMAT_RGBA32:
default:
return GL_RGBA8;
case KINC_IMAGE_FORMAT_A32:
return GL_R32F;
case KINC_IMAGE_FORMAT_A16:
return GL_R16F;
case KINC_IMAGE_FORMAT_GREY8:
return GL_R8;
}
}
static int convertInternalRTFormat(kinc_g4_render_target_format_t format) {
switch (format) {
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
return GL_RGBA16F;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
return GL_R32F;
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
return GL_RGBA32F;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH:
return GL_DEPTH_COMPONENT16;
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
return GL_RED;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
return GL_R16F;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
return GL_RGBA;
}
}
#endif
void kinc_g4_compute_shader_init(kinc_g4_compute_shader *shader, void *source, int length) {
shader->impl._length = length;
shader->impl.textureCount = 0;
shader->impl._source = (char *)malloc(sizeof(char) * (length + 1));
for (int i = 0; i < length; ++i) {
shader->impl._source[i] = ((char *)source)[i];
}
shader->impl._source[length] = 0;
#ifdef HAS_COMPUTE
shader->impl._id = glCreateShader(GL_COMPUTE_SHADER);
glCheckErrors();
glShaderSource(shader->impl._id, 1, (const GLchar **)&shader->impl._source, NULL);
glCompileShader(shader->impl._id);
int result;
glGetShaderiv(shader->impl._id, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetShaderiv(shader->impl._id, GL_INFO_LOG_LENGTH, &length);
char *errormessage = (char *)malloc(sizeof(char) * length);
glGetShaderInfoLog(shader->impl._id, length, NULL, errormessage);
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL compiler error: %s\n", errormessage);
free(errormessage);
}
shader->impl._programid = glCreateProgram();
glAttachShader(shader->impl._programid, shader->impl._id);
glLinkProgram(shader->impl._programid);
glGetProgramiv(shader->impl._programid, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetProgramiv(shader->impl._programid, GL_INFO_LOG_LENGTH, &length);
char *errormessage = (char *)malloc(sizeof(char) * length);
glGetProgramInfoLog(shader->impl._programid, length, NULL, errormessage);
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL linker error: %s\n", errormessage);
free(errormessage);
}
#endif
// TODO: Get rid of allocations
shader->impl.textures = (char **)malloc(sizeof(char *) * 16);
for (int i = 0; i < 16; ++i) {
shader->impl.textures[i] = (char *)malloc(sizeof(char) * 128);
shader->impl.textures[i][0] = 0;
}
shader->impl.textureValues = (int *)malloc(sizeof(int) * 16);
}
void kinc_g4_compute_shader_destroy(kinc_g4_compute_shader *shader) {
free(shader->impl._source);
shader->impl._source = NULL;
#ifdef HAS_COMPUTE
glDeleteProgram(shader->impl._programid);
glDeleteShader(shader->impl._id);
#endif
}
kinc_g4_constant_location_t kinc_g4_compute_shader_get_constant_location(kinc_g4_compute_shader *shader, const char *name) {
kinc_g4_constant_location_t location;
#ifdef HAS_COMPUTE
location.impl.location = glGetUniformLocation(shader->impl._programid, name);
location.impl.type = GL_FLOAT;
GLint count = 0;
glGetProgramiv(shader->impl._programid, GL_ACTIVE_UNIFORMS, &count);
char arrayName[1024];
strcpy(arrayName, name);
strcat(arrayName, "[0]");
for (GLint i = 0; i < count; ++i) {
GLenum type;
char uniformName[1024];
GLsizei length;
GLint size;
glGetActiveUniform(shader->impl._programid, i, 1024 - 1, &length, &size, &type, uniformName);
if (strcmp(uniformName, name) == 0 || strcmp(uniformName, arrayName) == 0) {
location.impl.type = type;
break;
}
}
glCheckErrors();
if (location.impl.location < 0) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
}
#endif
return location;
}
static int compute_findTexture(kinc_g4_compute_shader *shader, const char *name) {
for (int index = 0; index < shader->impl.textureCount; ++index) {
if (strcmp(shader->impl.textures[index], name) == 0)
return index;
}
return -1;
}
kinc_g4_texture_unit_t kinc_g4_compute_shader_get_texture_unit(kinc_g4_compute_shader *shader, const char *name) {
int index = compute_findTexture(shader, name);
if (index < 0) {
int location = glGetUniformLocation(shader->impl._programid, name);
glCheckErrors();
index = shader->impl.textureCount;
shader->impl.textureValues[index] = location;
strcpy(shader->impl.textures[index], name);
++shader->impl.textureCount;
}
kinc_g4_texture_unit_t unit;
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
unit.stages[i] = -1;
}
unit.stages[KINC_G4_SHADER_TYPE_COMPUTE] = index;
return unit;
}
void kinc_g4_set_shader_storage_buffer(kinc_shader_storage_buffer_t *buffer, int index) {
#ifdef HAS_COMPUTE
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer->impl.bufferId);
glCheckErrors();
#endif
}
void kinc_g4_set_compute_shader(kinc_g4_compute_shader *shader) {
#ifdef HAS_COMPUTE
glUseProgram(shader->impl._programid);
glCheckErrors();
for (int index = 0; index < shader->impl.textureCount; ++index) {
glUniform1i(shader->impl.textureValues[index], index);
glCheckErrors();
}
#endif
}
void kinc_g4_compute(int x, int y, int z) {
#ifdef HAS_COMPUTE
glDispatchCompute(x, y, z);
glCheckErrors();
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glCheckErrors();
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glCheckErrors();
#endif
}

View File

@ -0,0 +1,20 @@
#pragma once
typedef struct kinc_g4_compute_constant_location_impl {
int location;
unsigned int type;
} kinc_g4_compute_constant_location_impl;
typedef struct kinc_g4_compute_texture_unit_impl {
int unit;
} kinc_g4_compute_texture_unit_impl;
typedef struct kinc_g4_compute_shader_impl {
char **textures;
int *textureValues;
int textureCount;
unsigned _id;
unsigned _programid;
char *_source;
int _length;
} kinc_g4_compute_shader_impl;

View File

@ -0,0 +1,53 @@
#ifdef KINC_KONG
#include <kinc/graphics4/constantbuffer.h>
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
buffer->impl.size = size;
buffer->impl.last_start = 0;
buffer->impl.last_size = size;
buffer->impl.data = malloc(size);
buffer->impl.buffer = 0;
glGenBuffers(1, &buffer->impl.buffer);
glBindBuffer(GL_UNIFORM_BUFFER, buffer->impl.buffer);
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
free(buffer->impl.data);
buffer->impl.data = NULL;
glDeleteBuffers(1, &buffer->impl.buffer);
buffer->impl.buffer = 0;
}
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
return kinc_g4_constant_buffer_lock(buffer, 0, kinc_g4_constant_buffer_size(buffer));
}
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
buffer->impl.last_start = start;
buffer->impl.last_size = size;
uint8_t *data = (uint8_t *)buffer->impl.data;
return &data[start];
}
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
kinc_g4_constant_buffer_unlock(buffer, buffer->impl.last_size);
}
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
glBindBuffer(GL_UNIFORM_BUFFER, buffer->impl.buffer);
glBufferSubData(GL_UNIFORM_BUFFER, buffer->impl.last_start, buffer->impl.last_size, buffer->impl.data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
return buffer->impl.size;
}
#endif

View File

@ -0,0 +1,15 @@
#pragma once
#ifdef KINC_KONG
#include <stddef.h>
typedef struct kinc_g4_constant_buffer_impl {
unsigned buffer;
void *data;
size_t size;
size_t last_start;
size_t last_size;
} kinc_g4_constant_buffer_impl;
#endif

View File

@ -0,0 +1,6 @@
#pragma once
#include "IndexBufferImpl.h"
#include "RenderTargetImpl.h"
#include "TextureImpl.h"
#include "VertexBufferImpl.h"

View File

@ -0,0 +1,105 @@
#include "ogl.h"
#include <kinc/graphics4/indexbuffer.h>
#include <stdlib.h>
kinc_g4_index_buffer_t *Kinc_Internal_CurrentIndexBuffer = NULL;
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
buffer->impl.count = count;
buffer->impl.format = format;
glGenBuffers(1, &buffer->impl.buffer_id);
glCheckErrors();
if (format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT) {
buffer->impl.data = malloc(count * sizeof(uint32_t));
}
else {
buffer->impl.data = malloc(count * sizeof(uint16_t));
}
if (format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT && kinc_internal_opengl_force_16bit_index_buffer) {
buffer->impl.converted_data = malloc(count * sizeof(uint16_t));
}
else {
buffer->impl.converted_data = NULL;
}
switch (usage) {
case KINC_G4_USAGE_STATIC:
buffer->impl.usage = GL_STATIC_DRAW;
break;
case KINC_G4_USAGE_DYNAMIC:
buffer->impl.usage = GL_DYNAMIC_DRAW;
break;
case KINC_G4_USAGE_READABLE:
buffer->impl.usage = GL_DYNAMIC_DRAW;
break;
}
}
void Kinc_Internal_IndexBufferUnset(kinc_g4_index_buffer_t *buffer) {
if (Kinc_Internal_CurrentIndexBuffer == buffer) {
Kinc_Internal_CurrentIndexBuffer = NULL;
}
}
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
Kinc_Internal_IndexBufferUnset(buffer);
glDeleteBuffers(1, &buffer->impl.buffer_id);
free(buffer->impl.data);
buffer->impl.data = NULL;
free(buffer->impl.converted_data);
buffer->impl.converted_data = NULL;
}
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
return buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? 4 : 2;
}
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
}
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
uint8_t *data = (uint8_t *)buffer->impl.data;
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
}
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->impl.buffer_id);
glCheckErrors();
if (buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT && kinc_internal_opengl_force_16bit_index_buffer) {
uint32_t *data = (uint32_t *)buffer->impl.data;
for (int i = 0; i < buffer->impl.count; ++i) {
buffer->impl.converted_data[i] = (uint16_t)data[i];
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer->impl.count * sizeof(uint16_t), buffer->impl.converted_data, buffer->impl.usage);
glCheckErrors();
}
else {
GLsizeiptr size =
buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_16BIT ? buffer->impl.count * sizeof(uint16_t) : buffer->impl.count * sizeof(uint32_t);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, buffer->impl.data, buffer->impl.usage);
glCheckErrors();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glCheckErrors();
}
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
kinc_g4_index_buffer_unlock_all(buffer);
}
void kinc_internal_g4_index_buffer_set(kinc_g4_index_buffer_t *buffer) {
Kinc_Internal_CurrentIndexBuffer = buffer;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->impl.buffer_id);
glCheckErrors();
}
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
return buffer->impl.count;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint16_t *converted_data;
void *data;
int count;
unsigned usage;
int format;
unsigned buffer_id;
} kinc_g4_index_buffer_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,66 @@
#pragma once
#ifdef KINC_WINDOWS
#include <GL/glew.h>
#include <GL/gl.h>
#endif
#ifdef KINC_MACOS
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif
#ifdef KINC_IOS
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <OpenGLES/ES3/gl.h>
#endif
#ifdef KINC_ANDROID
#include <EGL/egl.h>
#if KINC_ANDROID_API >= 18
#include <GLES3/gl3.h>
#endif
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif
#ifdef KINC_EMSCRIPTEN
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#include <GL/gl.h>
#endif
#ifdef KINC_LINUX
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#endif
#ifdef KINC_RASPBERRY_PI
// #define GL_GLEXT_PROTOTYPES
#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"
#endif
#ifdef KINC_WASM
#include <GL/gl.h>
#endif
#include <kinc/log.h>
#ifdef NDEBUG
#define glCheckErrors() \
{}
#else
#define glCheckErrors() \
{ \
GLenum code = glGetError(); \
if (code != GL_NO_ERROR) { \
kinc_log(KINC_LOG_LEVEL_ERROR, "GL Error %d %s %d\n", code, __FILE__, __LINE__); \
} \
}
#endif

View File

@ -0,0 +1,18 @@
#include <stdbool.h>
static bool kinc_internal_opengl_force_16bit_index_buffer = false;
static int kinc_internal_opengl_max_vertex_attribute_arrays = 0;
#include "OpenGL.c.h"
#include "OpenGLWindow.c.h"
#include "ShaderStorageBufferImpl.c.h"
#include "VrInterface.c.h"
#include "compute.c.h"
#include "constantbuffer.c.h"
#include "indexbuffer.c.h"
#include "pipeline.c.h"
#include "rendertarget.c.h"
#include "shader.c.h"
#include "texture.c.h"
#include "texturearray.c.h"
#include "vertexbuffer.c.h"

View File

@ -0,0 +1,482 @@
#include <kinc/global.h>
#include "ogl.h"
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics4/vertexstructure.h>
#include <kinc/log.h>
#include <kinc/backend/graphics4/OpenGL.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef KINC_OPENGL_ES
bool Kinc_Internal_ProgramUsesTessellation = false;
#endif
extern bool Kinc_Internal_SupportsConservativeRaster;
static GLenum convertStencilAction(kinc_g4_stencil_action_t action) {
switch (action) {
default:
case KINC_G4_STENCIL_DECREMENT:
return GL_DECR;
case KINC_G4_STENCIL_DECREMENT_WRAP:
return GL_DECR_WRAP;
case KINC_G4_STENCIL_INCREMENT:
return GL_INCR;
case KINC_G4_STENCIL_INCREMENT_WRAP:
return GL_INCR_WRAP;
case KINC_G4_STENCIL_INVERT:
return GL_INVERT;
case KINC_G4_STENCIL_KEEP:
return GL_KEEP;
case KINC_G4_STENCIL_REPLACE:
return GL_REPLACE;
case KINC_G4_STENCIL_ZERO:
return GL_ZERO;
}
}
static GLenum convert_blend_factor(kinc_g4_blending_factor_t factor) {
switch (factor) {
case KINC_G4_BLEND_ZERO:
return GL_ZERO;
case KINC_G4_BLEND_ONE:
return GL_ONE;
case KINC_G4_BLEND_SOURCE_ALPHA:
return GL_SRC_ALPHA;
case KINC_G4_BLEND_DEST_ALPHA:
return GL_DST_ALPHA;
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
return GL_ONE_MINUS_SRC_ALPHA;
case KINC_G4_BLEND_INV_DEST_ALPHA:
return GL_ONE_MINUS_DST_ALPHA;
case KINC_G4_BLEND_SOURCE_COLOR:
return GL_SRC_COLOR;
case KINC_G4_BLEND_DEST_COLOR:
return GL_DST_COLOR;
case KINC_G4_BLEND_INV_SOURCE_COLOR:
return GL_ONE_MINUS_SRC_COLOR;
case KINC_G4_BLEND_INV_DEST_COLOR:
return GL_ONE_MINUS_DST_COLOR;
case KINC_G4_BLEND_CONSTANT:
return GL_CONSTANT_COLOR;
case KINC_G4_BLEND_INV_CONSTANT:
return GL_ONE_MINUS_CONSTANT_COLOR;
default:
assert(false);
return GL_ONE;
}
}
static GLenum convert_blend_operation(kinc_g4_blending_operation_t operation) {
switch (operation) {
case KINC_G4_BLENDOP_ADD:
return GL_FUNC_ADD;
case KINC_G4_BLENDOP_SUBTRACT:
return GL_FUNC_SUBTRACT;
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
return GL_FUNC_REVERSE_SUBTRACT;
case KINC_G4_BLENDOP_MIN:
return GL_MIN;
case KINC_G4_BLENDOP_MAX:
return GL_MAX;
default:
assert(false);
return GL_FUNC_ADD;
}
}
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *state) {
memset(state, 0, sizeof(kinc_g4_pipeline_t));
kinc_g4_internal_pipeline_set_defaults(state);
state->impl.textureCount = 0;
// TODO: Get rid of allocations
state->impl.textures = (char **)malloc(sizeof(char *) * 16);
for (int i = 0; i < 16; ++i) {
state->impl.textures[i] = (char *)malloc(sizeof(char) * 128);
state->impl.textures[i][0] = 0;
}
state->impl.textureValues = (int *)malloc(sizeof(int) * 16);
state->impl.programId = glCreateProgram();
glCheckErrors();
}
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *state) {
for (int i = 0; i < 16; ++i) {
free(state->impl.textures[i]);
}
free(state->impl.textures);
free(state->impl.textureValues);
glDeleteProgram(state->impl.programId);
}
static int toGlShader(kinc_g4_shader_type_t type) {
switch (type) {
case KINC_G4_SHADER_TYPE_VERTEX:
default:
return GL_VERTEX_SHADER;
case KINC_G4_SHADER_TYPE_FRAGMENT:
return GL_FRAGMENT_SHADER;
#ifndef KINC_OPENGL_ES
case KINC_G4_SHADER_TYPE_GEOMETRY:
return GL_GEOMETRY_SHADER;
case KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL:
return GL_TESS_CONTROL_SHADER;
case KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION:
return GL_TESS_EVALUATION_SHADER;
#endif
}
}
static void compileShader(unsigned *id, const char *source, size_t length, kinc_g4_shader_type_t type) {
*id = glCreateShader(toGlShader(type));
glCheckErrors();
glShaderSource(*id, 1, (const GLchar **)&source, 0);
glCompileShader(*id);
int result;
glGetShaderiv(*id, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE) {
int length = 0;
glGetShaderiv(*id, GL_INFO_LOG_LENGTH, &length);
char *errormessage = (char *)malloc(length);
glGetShaderInfoLog(*id, length, NULL, errormessage);
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL compiler error: %s", errormessage);
free(errormessage);
}
}
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *state) {
compileShader(&state->vertex_shader->impl._glid, state->vertex_shader->impl.source, state->vertex_shader->impl.length, KINC_G4_SHADER_TYPE_VERTEX);
compileShader(&state->fragment_shader->impl._glid, state->fragment_shader->impl.source, state->fragment_shader->impl.length, KINC_G4_SHADER_TYPE_FRAGMENT);
#ifndef KINC_OPENGL_ES
if (state->geometry_shader != NULL) {
compileShader(&state->geometry_shader->impl._glid, state->geometry_shader->impl.source, state->geometry_shader->impl.length,
KINC_G4_SHADER_TYPE_GEOMETRY);
}
if (state->tessellation_control_shader != NULL) {
compileShader(&state->tessellation_control_shader->impl._glid, state->tessellation_control_shader->impl.source,
state->tessellation_control_shader->impl.length, KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
}
if (state->tessellation_evaluation_shader != NULL) {
compileShader(&state->tessellation_evaluation_shader->impl._glid, state->tessellation_evaluation_shader->impl.source,
state->tessellation_evaluation_shader->impl.length, KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
}
#endif
glAttachShader(state->impl.programId, state->vertex_shader->impl._glid);
glAttachShader(state->impl.programId, state->fragment_shader->impl._glid);
#ifndef KINC_OPENGL_ES
if (state->geometry_shader != NULL) {
glAttachShader(state->impl.programId, state->geometry_shader->impl._glid);
}
if (state->tessellation_control_shader != NULL) {
glAttachShader(state->impl.programId, state->tessellation_control_shader->impl._glid);
}
if (state->tessellation_evaluation_shader != NULL) {
glAttachShader(state->impl.programId, state->tessellation_evaluation_shader->impl._glid);
}
#endif
glCheckErrors();
int index = 0;
for (int i1 = 0; state->input_layout[i1] != NULL; ++i1) {
for (int i2 = 0; i2 < state->input_layout[i1]->size; ++i2) {
kinc_g4_vertex_element_t element = state->input_layout[i1]->elements[i2];
glBindAttribLocation(state->impl.programId, index, element.name);
glCheckErrors();
if (element.data == KINC_G4_VERTEX_DATA_F32_4X4) {
index += 4;
}
else {
++index;
}
}
}
glLinkProgram(state->impl.programId);
int result;
glGetProgramiv(state->impl.programId, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
int length = 0;
glGetProgramiv(state->impl.programId, GL_INFO_LOG_LENGTH, &length);
char *errormessage = (char *)malloc(length);
glGetProgramInfoLog(state->impl.programId, length, NULL, errormessage);
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL linker error: %s", errormessage);
free(errormessage);
}
#ifndef KINC_OPENGL_ES
#ifndef KINC_LINUX
if (state->tessellation_control_shader != NULL) {
glPatchParameteri(GL_PATCH_VERTICES, 3);
glCheckErrors();
}
#endif
#endif
}
void kinc_g4_internal_set_pipeline(kinc_g4_pipeline_t *pipeline) {
#ifndef KINC_OPENGL_ES
Kinc_Internal_ProgramUsesTessellation = pipeline->tessellation_control_shader != NULL;
#endif
glUseProgram(pipeline->impl.programId);
glCheckErrors();
for (int index = 0; index < pipeline->impl.textureCount; ++index) {
glUniform1i(pipeline->impl.textureValues[index], index);
glCheckErrors();
}
if (pipeline->stencil_front_mode == KINC_G4_COMPARE_ALWAYS && pipeline->stencil_back_mode == KINC_G4_COMPARE_ALWAYS &&
pipeline->stencil_front_both_pass == KINC_G4_STENCIL_KEEP && pipeline->stencil_back_both_pass == KINC_G4_STENCIL_KEEP &&
pipeline->stencil_front_depth_fail == KINC_G4_STENCIL_KEEP && pipeline->stencil_back_depth_fail == KINC_G4_STENCIL_KEEP &&
pipeline->stencil_front_fail == KINC_G4_STENCIL_KEEP && pipeline->stencil_back_fail == KINC_G4_STENCIL_KEEP) {
glDisable(GL_STENCIL_TEST);
}
else {
glEnable(GL_STENCIL_TEST);
glStencilMaskSeparate(GL_FRONT, pipeline->stencil_write_mask);
glStencilOpSeparate(GL_FRONT, convertStencilAction(pipeline->stencil_front_fail), convertStencilAction(pipeline->stencil_front_depth_fail),
convertStencilAction(pipeline->stencil_front_both_pass));
glStencilFuncSeparate(GL_FRONT, Kinc_G4_Internal_StencilFunc(pipeline->stencil_front_mode), pipeline->stencil_reference_value,
pipeline->stencil_read_mask);
glStencilMaskSeparate(GL_BACK, pipeline->stencil_write_mask);
glStencilOpSeparate(GL_BACK, convertStencilAction(pipeline->stencil_back_fail), convertStencilAction(pipeline->stencil_back_depth_fail),
convertStencilAction(pipeline->stencil_back_both_pass));
glStencilFuncSeparate(GL_BACK, Kinc_G4_Internal_StencilFunc(pipeline->stencil_back_mode), pipeline->stencil_reference_value,
pipeline->stencil_read_mask);
}
#ifdef KINC_OPENGL_ES
glColorMask(pipeline->color_write_mask_red[0], pipeline->color_write_mask_green[0], pipeline->color_write_mask_blue[0],
pipeline->color_write_mask_alpha[0]);
#else
for (int i = 0; i < 8; ++i)
glColorMaski(i, pipeline->color_write_mask_red[i], pipeline->color_write_mask_green[i], pipeline->color_write_mask_blue[i],
pipeline->color_write_mask_alpha[i]);
#endif
if (Kinc_Internal_SupportsConservativeRaster) {
if (pipeline->conservative_rasterization) {
glEnable(0x9346); // GL_CONSERVATIVE_RASTERIZATION_NV
}
else {
glDisable(0x9346);
}
}
glCheckErrors();
/*switch (state) {
case Normalize:
device->SetRenderState(D3DRS_NORMALIZENORMALS, on ? TRUE : FALSE);
break;
case BackfaceCulling:
if (on) device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
else device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
break;
case FogState:
device->SetRenderState(D3DRS_FOGENABLE, on ? TRUE : FALSE);
break;
case ScissorTestState:
device->SetRenderState(D3DRS_SCISSORTESTENABLE, on ? TRUE : FALSE);
break;
case AlphaTestState:
device->SetRenderState(D3DRS_ALPHATESTENABLE, on ? TRUE : FALSE);
device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
break;
default:
throw Exception();
}*/
if (pipeline->depth_write) {
glDepthMask(GL_TRUE);
}
else {
glDepthMask(GL_FALSE);
}
if (pipeline->depth_mode != KINC_G4_COMPARE_ALWAYS) {
glEnable(GL_DEPTH_TEST);
}
else {
glDisable(GL_DEPTH_TEST);
}
GLenum func = GL_ALWAYS;
switch (pipeline->depth_mode) {
default:
case KINC_G4_COMPARE_ALWAYS:
func = GL_ALWAYS;
break;
case KINC_G4_COMPARE_NEVER:
func = GL_NEVER;
break;
case KINC_G4_COMPARE_EQUAL:
func = GL_EQUAL;
break;
case KINC_G4_COMPARE_NOT_EQUAL:
func = GL_NOTEQUAL;
break;
case KINC_G4_COMPARE_LESS:
func = GL_LESS;
break;
case KINC_G4_COMPARE_LESS_EQUAL:
func = GL_LEQUAL;
break;
case KINC_G4_COMPARE_GREATER:
func = GL_GREATER;
break;
case KINC_G4_COMPARE_GREATER_EQUAL:
func = GL_GEQUAL;
break;
}
glDepthFunc(func);
glCheckErrors();
switch (pipeline->cull_mode) {
case KINC_G4_CULL_CLOCKWISE:
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glCheckErrors();
break;
case KINC_G4_CULL_COUNTER_CLOCKWISE:
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glCheckErrors();
break;
case KINC_G4_CULL_NOTHING:
glDisable(GL_CULL_FACE);
glCheckErrors();
break;
default:
break;
}
/*switch (state) {
case DepthTestCompare:
switch (v) {
// TODO: Cmp-Konstanten systemabhaengig abgleichen
default:
case ZCmp_Always : v = D3DCMP_ALWAYS; break;
case ZCmp_Never : v = D3DCMP_NEVER; break;
case ZCmp_Equal : v = D3DCMP_EQUAL; break;
case ZCmp_NotEqual : v = D3DCMP_NOTEQUAL; break;
case ZCmp_Less : v = D3DCMP_LESS; break;
case ZCmp_LessEqual : v = D3DCMP_LESSEQUAL; break;
case ZCmp_Greater : v = D3DCMP_GREATER; break;
case ZCmp_GreaterEqual: v = D3DCMP_GREATEREQUAL; break;
}
device->SetRenderState(D3DRS_ZFUNC, v);
break;
case FogTypeState:
switch (v) {
case LinearFog:
device->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
}
break;
case AlphaReferenceState:
device->SetRenderState(D3DRS_ALPHAREF, (DWORD)v);
break;
default:
throw Exception();
}*/
if (pipeline->blend_source != KINC_G4_BLEND_ONE || pipeline->blend_destination != KINC_G4_BLEND_ZERO || pipeline->alpha_blend_source != KINC_G4_BLEND_ONE ||
pipeline->alpha_blend_destination != KINC_G4_BLEND_ZERO) {
glEnable(GL_BLEND);
}
else {
glDisable(GL_BLEND);
}
// glBlendFunc(convert(pipeline->blendSource), convert(pipeline->blendDestination));
glBlendFuncSeparate(convert_blend_factor(pipeline->blend_source), convert_blend_factor(pipeline->blend_destination),
convert_blend_factor(pipeline->alpha_blend_source), convert_blend_factor(pipeline->alpha_blend_destination));
glBlendEquationSeparate(convert_blend_operation(pipeline->blend_operation), convert_blend_operation(pipeline->alpha_blend_operation));
}
void kinc_g4_pipeline_get_constant_locations(kinc_g4_pipeline_t *state, kinc_g4_constant_location_t *vertex_locations,
kinc_g4_constant_location_t *fragment_locations, int *vertex_sizes, int *fragment_sizes, int *max_vertex,
int *max_fragment) {
// GLint count = 0;
// glGetProgramiv(state->impl.programId, GL_ACTIVE_UNIFORMS, &count);
// if (locations == NULL || sizes == NULL) {
// *max_count = count;
// }
// else {
// for (GLint i = 0; i < count; ++i) {
// GLenum type;
// char uniformName[1024];
// GLsizei length;
// GLint size;
// glGetActiveUniform(state->impl.programId, i, 1024 - 1, &length, &size, &type, uniformName);
// locations[i].impl.location = glGetUniformLocation(state->impl.programId, uniformName);
// locations[i].impl.type = type;
// sizes[i] = size;
// }
// }
}
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *state, const char *name) {
kinc_g4_constant_location_t location;
location.impl.location = glGetUniformLocation(state->impl.programId, name);
location.impl.type = GL_FLOAT;
GLint count = 0;
glGetProgramiv(state->impl.programId, GL_ACTIVE_UNIFORMS, &count);
char arrayName[1024];
strcpy(arrayName, name);
strcat(arrayName, "[0]");
for (GLint i = 0; i < count; ++i) {
GLenum type;
char uniformName[1024];
GLsizei length;
GLint size;
glGetActiveUniform(state->impl.programId, i, 1024 - 1, &length, &size, &type, uniformName);
if (strcmp(uniformName, name) == 0 || strcmp(uniformName, arrayName) == 0) {
location.impl.type = type;
break;
}
}
glCheckErrors();
if (location.impl.location < 0) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
}
return location;
}
static int findTexture(kinc_g4_pipeline_t *state, const char *name) {
for (int index = 0; index < state->impl.textureCount; ++index) {
if (strcmp(state->impl.textures[index], name) == 0)
return index;
}
return -1;
}
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *state, const char *name) {
int index = findTexture(state, name);
if (index < 0) {
int location = glGetUniformLocation(state->impl.programId, name);
glCheckErrors();
index = state->impl.textureCount;
state->impl.textureValues[index] = location;
strcpy(state->impl.textures[index], name);
++state->impl.textureCount;
}
kinc_g4_texture_unit_t unit;
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
unit.stages[i] = -1;
}
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = index;
return unit;
}

View File

@ -0,0 +1,16 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned programId;
char **textures;
int *textureValues;
int textureCount;
} kinc_g4_pipeline_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,421 @@
#include <kinc/graphics4/rendertarget.h>
#include "ogl.h"
#include <kinc/backend/graphics4/OpenGL.h>
#include <kinc/graphics4/graphics.h>
#include <kinc/log.h>
#include <kinc/system.h>
#ifndef GL_RGBA16F_EXT
#define GL_RGBA16F_EXT 0x881A
#endif
#ifndef GL_RGBA32F_EXT
#define GL_RGBA32F_EXT 0x8814
#endif
#ifndef GL_R16F_EXT
#define GL_R16F_EXT 0x822D
#endif
#ifndef GL_R32F_EXT
#define GL_R32F_EXT 0x822E
#endif
#ifndef GL_HALF_FLOAT
#define GL_HALF_FLOAT 0x140B
#endif
#ifndef GL_RED
#define GL_RED GL_LUMINANCE
#endif
#ifndef GL_R8
#define GL_R8 GL_RED
#endif
extern bool Kinc_Internal_SupportsDepthTexture;
static int pow2(int pow) {
int ret = 1;
for (int i = 0; i < pow; ++i)
ret *= 2;
return ret;
}
static int getPower2(int i) {
for (int power = 0;; ++power)
if (pow2(power) >= i)
return pow2(power);
}
#ifdef KINC_OPENGL_ES
extern int gles_version;
#endif
bool kinc_opengl_internal_nonPow2RenderTargetsSupported() {
#ifdef KINC_OPENGL_ES
return gles_version >= 3;
#else
return true;
#endif
}
static void setupDepthStencil(kinc_g4_render_target_t *renderTarget, GLenum texType, int depthBufferBits, int stencilBufferBits, int width, int height) {
if (depthBufferBits > 0 && stencilBufferBits > 0) {
renderTarget->impl._hasDepth = true;
#if defined(KINC_OPENGL_ES) && !defined(KINC_RASPBERRY_PI) && !defined(KINC_EMSCRIPTEN)
GLenum internalFormat = GL_DEPTH24_STENCIL8_OES;
#elif defined(KINC_OPENGL_ES)
GLenum internalFormat = 0x88F0; // GL_DEPTH24_STENCIL8_OES
#else
GLenum internalFormat;
if (depthBufferBits == 24)
internalFormat = GL_DEPTH24_STENCIL8;
else
internalFormat = GL_DEPTH32F_STENCIL8;
#endif
// Renderbuffer
// glGenRenderbuffers(1, &_depthRenderbuffer);
// glCheckErrors();
// glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
// glCheckErrors();
// glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
// glCheckErrors();
// #ifdef KINC_OPENGL_ES
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// #else
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// #endif
// glCheckErrors();
// Texture
glGenTextures(1, &renderTarget->impl._depthTexture);
glCheckErrors();
glBindTexture(texType, renderTarget->impl._depthTexture);
glCheckErrors();
glTexImage2D(texType, 0, internalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glCheckErrors();
glTexParameteri(texType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
glCheckErrors();
#ifdef KINC_OPENGL_ES
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
#else
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
#endif
glCheckErrors();
}
else if (depthBufferBits > 0) {
renderTarget->impl._hasDepth = true;
if (!Kinc_Internal_SupportsDepthTexture) {
// Renderbuffer
glGenRenderbuffers(1, &renderTarget->impl._depthTexture);
glCheckErrors();
glBindRenderbuffer(GL_RENDERBUFFER, renderTarget->impl._depthTexture);
glCheckErrors();
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glCheckErrors();
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderTarget->impl._depthTexture);
glCheckErrors();
}
else {
// Texture
glGenTextures(1, &renderTarget->impl._depthTexture);
glCheckErrors();
glBindTexture(texType, renderTarget->impl._depthTexture);
glCheckErrors();
#if defined(KINC_EMSCRIPTEN) || defined(KINC_WASM)
GLint format = GL_DEPTH_COMPONENT16;
#else
GLint format = depthBufferBits == 16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT;
#endif
glTexImage2D(texType, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glCheckErrors();
glTexParameteri(texType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
glCheckErrors();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
glCheckErrors();
}
}
}
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
renderTarget->width = width;
renderTarget->height = height;
renderTarget->isCubeMap = false;
renderTarget->isDepthAttachment = false;
renderTarget->impl._hasDepth = false;
if (kinc_opengl_internal_nonPow2RenderTargetsSupported()) {
renderTarget->texWidth = width;
renderTarget->texHeight = height;
}
else {
renderTarget->texWidth = getPower2(width);
renderTarget->texHeight = getPower2(height);
}
renderTarget->impl.format = (int)format;
glGenTextures(1, &renderTarget->impl._texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, renderTarget->impl._texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
switch (format) {
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
#ifdef KINC_OPENGL_ES
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
#endif
break;
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
#ifdef KINC_OPENGL_ES
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
#endif
break;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH:
#ifdef KINC_OPENGL_ES
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, renderTarget->texWidth, renderTarget->texHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
break;
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
#ifdef KINC_IOS
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
#endif
break;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_HALF_FLOAT, 0);
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_FLOAT, 0);
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
glCheckErrors();
glGenFramebuffers(1, &renderTarget->impl._framebuffer);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
glCheckErrors();
setupDepthStencil(renderTarget, GL_TEXTURE_2D, depthBufferBits, stencilBufferBits, renderTarget->texWidth, renderTarget->texHeight);
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderTarget->impl._texture, 0);
#ifndef KINC_OPENGL_ES
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
#endif
}
else {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget->impl._texture, 0);
}
glCheckErrors();
// GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
// glDrawBuffers(1, drawBuffers);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, 0);
glCheckErrors();
}
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
renderTarget->width = cubeMapSize;
renderTarget->height = cubeMapSize;
renderTarget->isCubeMap = true;
renderTarget->isDepthAttachment = false;
renderTarget->impl._hasDepth = false;
if (kinc_opengl_internal_nonPow2RenderTargetsSupported()) {
renderTarget->texWidth = renderTarget->width;
renderTarget->texHeight = renderTarget->height;
}
else {
renderTarget->texWidth = getPower2(renderTarget->width);
renderTarget->texHeight = getPower2(renderTarget->height);
}
renderTarget->impl.format = (int)format;
glGenTextures(1, &renderTarget->impl._texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_CUBE_MAP, renderTarget->impl._texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
switch (format) {
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
#ifdef KINC_OPENGL_ES
for (int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
#else
for (int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
#endif
break;
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
#ifdef KINC_OPENGL_ES
for (int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
#else
for (int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
#endif
break;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH:
#ifdef KINC_OPENGL_ES
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#endif
for (int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT16, renderTarget->texWidth, renderTarget->texHeight, 0, GL_DEPTH_COMPONENT,
GL_UNSIGNED_INT, 0);
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
for (int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
glCheckErrors();
glGenFramebuffers(1, &renderTarget->impl._framebuffer);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
glCheckErrors();
setupDepthStencil(renderTarget, GL_TEXTURE_CUBE_MAP, depthBufferBits, stencilBufferBits, renderTarget->texWidth, renderTarget->texHeight);
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
renderTarget->isDepthAttachment = true;
#ifndef KINC_OPENGL_ES
glDrawBuffer(GL_NONE);
glCheckErrors();
glReadBuffer(GL_NONE);
glCheckErrors();
#endif
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glCheckErrors();
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glCheckErrors();
}
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
{
GLuint textures[] = {renderTarget->impl._texture};
glDeleteTextures(1, textures);
}
if (renderTarget->impl._hasDepth) {
GLuint textures[] = {renderTarget->impl._depthTexture};
glDeleteTextures(1, textures);
}
GLuint framebuffers[] = {renderTarget->impl._framebuffer};
glDeleteFramebuffers(1, framebuffers);
}
#ifdef KINC_KONG
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glCheckErrors();
glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._texture);
glCheckErrors();
}
#else
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
glCheckErrors();
glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._texture);
glCheckErrors();
}
#endif
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
glCheckErrors();
glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._depthTexture);
glCheckErrors();
}
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
renderTarget->impl._depthTexture = source->impl._depthTexture;
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._depthTexture,
0);
}
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
switch ((kinc_g4_render_target_format_t)renderTarget->impl.format) {
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RGBA, GL_FLOAT, data);
break;
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RGBA, GL_HALF_FLOAT, data);
break;
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RED, GL_UNSIGNED_BYTE, data);
break;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RED, GL_HALF_FLOAT, data);
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RED, GL_FLOAT, data);
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
}
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {
glBindTexture(GL_TEXTURE_2D, renderTarget->impl._texture);
glCheckErrors();
glGenerateMipmap(GL_TEXTURE_2D);
glCheckErrors();
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned _framebuffer;
unsigned _texture;
unsigned _depthTexture;
bool _hasDepth;
// unsigned _depthRenderbuffer;
int format;
} kinc_g4_render_target_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,53 @@
#include "ogl.h"
#include <kinc/graphics4/shader.h>
#include <stdlib.h>
#include <string.h>
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *data, size_t length, kinc_g4_shader_type_t type) {
shader->impl.length = length;
shader->impl._glid = 0;
char *source = (char *)malloc(length + 1);
memcpy(source, data, length);
source[length] = 0;
shader->impl.source = source;
}
#ifdef KRAFIX_LIBRARY
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
#endif
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
#ifdef KRAFIX_LIBRARY
char *output = malloc(1024 * 1024);
int length;
#ifdef KINC_WINDOWS
const char *system = "windows";
#elif defined(KINC_MACOS)
const char *system = "macos";
#elif defined(KINC_LINUX)
const char *system = "linux";
#elif defined(KINC_ANDROID)
const char *system = "android";
#elif defined(KINC_IOS)
const char *system = "ios";
#endif
int errors = krafix_compile(source, output, &length, "glsl", system, type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
if (errors > 0) {
return errors;
}
kinc_g4_shader_init(shader, output, length, type);
return 0;
#else
return 0;
#endif
}
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
free((void *)shader->impl.source);
shader->impl.source = NULL;
if (shader->impl._glid != 0) {
glDeleteShader(shader->impl._glid);
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned _glid;
const char *source;
size_t length;
} kinc_g4_shader_impl_t;
typedef struct {
int location;
unsigned type;
} kinc_g4_constant_location_impl_t;
typedef struct {
int unit;
} kinc_g4_texture_unit_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,648 @@
#include <kinc/graphics4/texture.h>
#include "ogl.h"
#include <kinc/graphics4/graphics.h>
#include <kinc/image.h>
#include <kinc/log.h>
#include <kinc/math/core.h>
#include "OpenGL.h"
#include <stdlib.h>
#ifndef GL_TEXTURE_3D
#define GL_TEXTURE_3D 0x806F
#endif
#ifndef GL_RGBA16F_EXT
#define GL_RGBA16F_EXT 0x881A
#endif
#ifndef GL_RGBA32F_EXT
#define GL_RGBA32F_EXT 0x8814
#endif
#ifndef GL_R16F_EXT
#define GL_R16F_EXT 0x822D
#endif
#ifndef GL_R32F_EXT
#define GL_R32F_EXT 0x822E
#endif
#ifndef GL_HALF_FLOAT
#define GL_HALF_FLOAT 0x140B
#endif
#ifndef GL_RED
#define GL_RED GL_LUMINANCE
#endif
#ifndef GL_R8
#define GL_R8 GL_RED
#endif
#ifndef GL_RGBA8
#define GL_RGBA8 GL_RGBA
#endif
#ifndef GL_KHR_texture_compression_astc_ldr
#define GL_KHR_texture_compression_astc_ldr 1
#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
#endif
static int convertFormat(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_BGRA32:
#ifdef GL_BGRA
return GL_BGRA;
#else
return GL_RGBA;
#endif
case KINC_IMAGE_FORMAT_RGBA32:
case KINC_IMAGE_FORMAT_RGBA64:
case KINC_IMAGE_FORMAT_RGBA128:
default:
return GL_RGBA;
case KINC_IMAGE_FORMAT_RGB24:
return GL_RGB;
case KINC_IMAGE_FORMAT_A32:
case KINC_IMAGE_FORMAT_A16:
case KINC_IMAGE_FORMAT_GREY8:
return GL_RED;
}
}
static int convertInternalFormat(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA128:
return GL_RGBA32F_EXT;
case KINC_IMAGE_FORMAT_RGBA64:
return GL_RGBA16F_EXT;
case KINC_IMAGE_FORMAT_RGBA32:
return GL_RGBA8;
default:
#ifdef KINC_IOS
return GL_RGBA;
#else
// #ifdef GL_BGRA
// return GL_BGRA;
// #else
return GL_RGBA;
// #endif
#endif
case KINC_IMAGE_FORMAT_RGB24:
return GL_RGB;
case KINC_IMAGE_FORMAT_A32:
return GL_R32F_EXT;
case KINC_IMAGE_FORMAT_A16:
return GL_R16F_EXT;
case KINC_IMAGE_FORMAT_GREY8:
#ifdef KINC_IOS
return GL_RED;
#else
return GL_R8;
#endif
}
}
static int convertType(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA128:
case KINC_IMAGE_FORMAT_RGBA64:
case KINC_IMAGE_FORMAT_A32:
case KINC_IMAGE_FORMAT_A16:
return GL_FLOAT;
case KINC_IMAGE_FORMAT_RGBA32:
default:
return GL_UNSIGNED_BYTE;
}
}
static int astcFormat(uint8_t blockX, uint8_t blockY) {
switch (blockX) {
case 4:
switch (blockY) {
case 4:
return GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
}
case 5:
switch (blockY) {
case 4:
return GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
case 5:
return GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
}
case 6:
switch (blockY) {
case 5:
return GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
case 6:
return GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
}
case 8:
switch (blockY) {
case 5:
return GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
case 6:
return GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
case 8:
return GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
}
case 10:
switch (blockY) {
case 5:
return GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
case 6:
return GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
case 8:
return GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
case 10:
return GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
}
case 12:
switch (blockY) {
case 10:
return GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
case 12:
return GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
}
}
return 0;
}
/*static int pow2(int pow) {
int ret = 1;
for (int i = 0; i < pow; ++i) ret *= 2;
return ret;
}
static int getPower2(int i) {
for (int power = 0;; ++power)
if (pow2(power) >= i) return pow2(power);
}*/
static void convertImageToPow2(kinc_image_format_t format, uint8_t *from, int fw, int fh, uint8_t *to, int tw, int th) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA32:
for (int y = 0; y < th; ++y) {
for (int x = 0; x < tw; ++x) {
to[tw * 4 * y + x * 4 + 0] = 0;
to[tw * 4 * y + x * 4 + 1] = 0;
to[tw * 4 * y + x * 4 + 2] = 0;
to[tw * 4 * y + x * 4 + 3] = 0;
}
}
for (int y = 0; y < fh; ++y) {
for (int x = 0; x < fw; ++x) {
to[tw * 4 * y + x * 4 + 0] = from[y * fw * 4 + x * 4 + 0];
to[tw * 4 * y + x * 4 + 1] = from[y * fw * 4 + x * 4 + 1];
to[tw * 4 * y + x * 4 + 2] = from[y * fw * 4 + x * 4 + 2];
to[tw * 4 * y + x * 4 + 3] = from[y * fw * 4 + x * 4 + 3];
}
}
break;
case KINC_IMAGE_FORMAT_GREY8:
for (int y = 0; y < th; ++y) {
for (int x = 0; x < tw; ++x) {
to[tw * y + x] = 0;
}
}
for (int y = 0; y < fh; ++y) {
for (int x = 0; x < fw; ++x) {
to[tw * y + x] = from[y * fw + x];
}
}
break;
case KINC_IMAGE_FORMAT_RGB24:
case KINC_IMAGE_FORMAT_RGBA128:
case KINC_IMAGE_FORMAT_RGBA64:
case KINC_IMAGE_FORMAT_A32:
case KINC_IMAGE_FORMAT_A16:
case KINC_IMAGE_FORMAT_BGRA32:
break;
}
}
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
texture->format = image->format;
bool toPow2;
#ifdef KINC_IOS
texture->tex_width = image->width;
texture->tex_height = image->height;
toPow2 = false;
#else
if (kinc_g4_supports_non_pow2_textures()) {
texture->tex_width = image->width;
texture->tex_height = image->height;
toPow2 = false;
}
else {
texture->tex_width = getPower2(image->width);
texture->tex_height = getPower2(image->height);
toPow2 = !(texture->tex_width == image->width && texture->tex_height == image->height);
}
#endif
texture->tex_depth = 1;
uint8_t *conversionBuffer = NULL;
switch (image->compression) {
case KINC_IMAGE_COMPRESSION_NONE:
if (toPow2) {
conversionBuffer = (uint8_t *)malloc(texture->tex_width * texture->tex_height * kinc_image_format_sizeof(image->format));
convertImageToPow2(image->format, (uint8_t *)image->data, image->width, image->height, conversionBuffer, texture->tex_width, texture->tex_height);
}
break;
case KINC_IMAGE_COMPRESSION_PVRTC:
texture->tex_width = kinc_maxi(texture->tex_width, texture->tex_height);
texture->tex_height = kinc_maxi(texture->tex_width, texture->tex_height);
if (texture->tex_width < 8)
texture->tex_width = 8;
if (texture->tex_height < 8)
texture->tex_height = 8;
break;
default:
texture->tex_width = image->width;
texture->tex_height = image->height;
break;
}
#ifdef KINC_ANDROID
texture->impl.external_oes = false;
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glCheckErrors();
glGenTextures(1, &texture->impl.texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, texture->impl.texture);
glCheckErrors();
int convertedType = convertType(image->format);
bool isHdr = convertedType == GL_FLOAT;
switch (image->compression) {
case KINC_IMAGE_COMPRESSION_PVRTC:
#ifdef KINC_IOS
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, texture->tex_width, texture->tex_height, 0,
texture->tex_width * texture->tex_height / 2, image->data);
#endif
break;
case KINC_IMAGE_COMPRESSION_ASTC: {
uint8_t blockX = image->internal_format >> 8;
uint8_t blockY = image->internal_format & 0xff;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, astcFormat(blockX, blockY), texture->tex_width, texture->tex_height, 0, image->data_size, image->data);
break;
}
case KINC_IMAGE_COMPRESSION_DXT5:
#ifdef KINC_WINDOWS
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, texture->tex_width, texture->tex_height, 0, image->data_size, image->data);
#endif
break;
case KINC_IMAGE_COMPRESSION_NONE: {
void *texdata = image->data;
if (!isHdr && toPow2) {
texdata = conversionBuffer;
}
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(image->format), texture->tex_width, texture->tex_height, 0, convertFormat(image->format),
convertedType, texdata);
glCheckErrors();
break;
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (toPow2) {
free(conversionBuffer);
conversionBuffer = NULL;
}
/*if (!readable) {
if (isHdr) {
free(texture->image.hdrData);
texture->image.hdrData = NULL;
}
else {
free(texture->image.data);
texture->image.data = NULL;
}
}
if (readable && texture->image.compression != KINC_IMAGE_COMPRESSION_NONE) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Compressed images can not be readable.");
}*/
}
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {
texture->format = image->format;
#ifndef KINC_OPENGL_ES // Requires GLES 3.0
texture->tex_width = image->width;
texture->tex_height = image->height;
texture->tex_depth = image->depth;
#ifdef KINC_ANDROID
external_oes = false;
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glCheckErrors();
glGenTextures(1, &texture->impl.texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_3D, texture->impl.texture);
glCheckErrors();
int convertedType = convertType(image->format);
// bool isHdr = convertedType == GL_FLOAT;
void *texdata = image->data;
glTexImage3D(GL_TEXTURE_3D, 0, convertInternalFormat(image->format), texture->tex_width, texture->tex_height, texture->tex_depth, 0,
convertFormat(image->format), convertedType, texdata);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
/*if (!readable) {
if (isHdr) {
free(texture->image.hdrData);
texture->image.hdrData = NULL;
}
else {
free(texture->image.data);
texture->image.data = NULL;
}
}
if (texture->image.compression != KINC_IMAGE_COMPRESSION_NONE) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Compressed images can not be 3D.");
}*/
#endif
}
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
#ifdef KINC_IOS
texture->tex_width = width;
texture->tex_height = height;
#else
if (kinc_g4_supports_non_pow2_textures()) {
texture->tex_width = width;
texture->tex_height = height;
}
else {
texture->tex_width = getPower2(width);
texture->tex_height = getPower2(height);
}
#endif
texture->tex_depth = 1;
texture->format = format;
// conversionBuffer = new u8[texWidth * texHeight * 4];
#ifdef KINC_ANDROID
texture->impl.external_oes = false;
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glCheckErrors();
glGenTextures(1, &texture->impl.texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, texture->impl.texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
if (convertType(format) == GL_FLOAT) {
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(format), texture->tex_width, texture->tex_height, 0, convertFormat(format), GL_FLOAT, NULL);
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(format), texture->tex_width, texture->tex_height, 0, convertFormat(format), GL_UNSIGNED_BYTE,
NULL);
}
glCheckErrors();
}
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {
#ifndef KINC_OPENGL_ES
texture->tex_width = width;
texture->tex_height = height;
texture->tex_depth = depth;
texture->format = format;
glGenTextures(1, &texture->impl.texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_3D, texture->impl.texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexImage3D(GL_TEXTURE_3D, 0, convertInternalFormat(format), width, height, depth, 0, convertFormat(format), GL_UNSIGNED_BYTE, NULL);
glCheckErrors();
#endif
}
#ifdef KINC_ANDROID
void kinc_g4_texture_init_from_id(kinc_g4_texture_t *texture, unsigned texid) {
texture->impl.texture = texid;
texture->impl.external_oes = true;
texture->tex_width = 1023;
texture->tex_height = 684;
texture->format = KINC_IMAGE_FORMAT_RGBA32;
}
#endif
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
glDeleteTextures(1, &texture->impl.texture);
glFlush();
}
#ifdef KINC_KONG
void Kinc_G4_Internal_TextureSet(kinc_g4_texture_t *texture, uint32_t unit) {
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glActiveTexture(GL_TEXTURE0 + unit);
glCheckErrors();
#ifdef KINC_ANDROID
if (texture->impl.external_oes) {
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->impl.texture);
glCheckErrors();
}
else {
glBindTexture(target, texture->impl.texture);
glCheckErrors();
}
#else
glBindTexture(target, texture->impl.texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Kinc_G4_Internal_TextureAddressingU(unit));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Kinc_G4_Internal_TextureAddressingV(unit));
#endif
}
#else
void Kinc_G4_Internal_TextureSet(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
glActiveTexture(GL_TEXTURE0 + unit.stages[i]);
}
}
glCheckErrors();
#ifdef KINC_ANDROID
if (texture->impl.external_oes) {
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->impl.texture);
glCheckErrors();
}
else {
glBindTexture(target, texture->impl.texture);
glCheckErrors();
}
#else
glBindTexture(target, texture->impl.texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Kinc_G4_Internal_TextureAddressingU(unit));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Kinc_G4_Internal_TextureAddressingV(unit));
#endif
}
#endif
void Kinc_G4_Internal_TextureImageSet(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
#if defined(KINC_WINDOWS) || (defined(KINC_LINUX) && defined(GL_VERSION_4_4))
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
glBindImageTexture(unit.stages[i], texture->impl.texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, convertInternalFormat(texture->format));
}
}
glCheckErrors();
#endif
}
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
return texture->tex_width * kinc_image_format_sizeof(texture->format);
}
static uint8_t *lock_cache = NULL;
unsigned char *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
if (lock_cache == NULL) {
lock_cache = (uint8_t *)malloc(4096 * 4096 * 4);
}
return lock_cache; //**(texture->image.data ? texture->image.data : (uint8_t *)texture->image.hdrData);
}
/*void Texture::unlock() {
if (conversionBuffer != nullptr) {
convertImageToPow2(format, (u8*)data, width, height, conversionBuffer, texWidth, texHeight);
glBindTexture(GL_TEXTURE_2D, texture);
#ifndef GL_LUMINANCE
#define GL_LUMINANCE GL_RED
#endif
glTexImage2D(GL_TEXTURE_2D, 0, (format == Image::RGBA32) ? GL_RGBA : GL_LUMINANCE, texWidth, texHeight, 0, (format == Image::RGBA32) ? GL_RGBA :
GL_LUMINANCE, GL_UNSIGNED_BYTE, conversionBuffer);
}
}*/
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
void *texdata = lock_cache;
glBindTexture(target, texture->impl.texture);
glCheckErrors();
if (texture->tex_depth > 1) {
#ifndef KINC_OPENGL_ES
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, texture->tex_width, texture->tex_height, texture->tex_depth, convertFormat(texture->format),
convertType(texture->format), texdata);
#endif
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->tex_width, texture->tex_height, convertFormat(texture->format), convertType(texture->format), texdata);
}
glCheckErrors();
}
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
#ifdef GL_VERSION_4_4
static float clearColor[4];
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
clearColor[2] = (color & 0x000000ff) / 255.0f;
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
GLenum target = depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glBindTexture(target, texture->impl.texture);
glClearTexSubImage(texture->impl.texture, 0, x, y, z, width, height, depth, convertFormat(texture->format), convertType(texture->format), clearColor);
#endif
}
#if defined(KINC_IOS) || defined(KINC_MACOS)
void kinc_g4_texture_upload(kinc_g4_texture_t *texture, uint8_t *data, int stride) {
glBindTexture(GL_TEXTURE_2D, texture->impl.texture);
glCheckErrors();
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->tex_width, texture->tex_height, convertFormat(texture->format), GL_UNSIGNED_BYTE, data);
glCheckErrors();
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
#endif
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glBindTexture(target, texture->impl.texture);
glCheckErrors();
glGenerateMipmap(target);
glCheckErrors();
}
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
int convertedType = convertType(mipmap->format);
// bool isHdr = convertedType == GL_FLOAT;
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glBindTexture(target, texture->impl.texture);
glCheckErrors();
glTexImage2D(target, level, convertInternalFormat(mipmap->format), mipmap->width, mipmap->height, 0, convertFormat(mipmap->format), convertedType,
mipmap->data);
glCheckErrors();
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned int texture;
#ifdef KINC_ANDROID
bool external_oes;
#endif
uint8_t pixfmt;
} kinc_g4_texture_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,25 @@
#include <kinc/graphics4/texturearray.h>
#include <kinc/graphics4/textureunit.h>
#include <kinc/backend/graphics4/ogl.h>
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {
#ifdef GL_VERSION_4_2
glGenTextures(1, &array->impl.texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, array->impl.texture);
// glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, textures[0].width, textures[0].height, count, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, textures[0].width, textures[0].height, count);
for (int i = 0; i < count; ++i) {
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, textures[i].width, textures[i].height, 1, GL_RGBA, GL_UNSIGNED_BYTE, textures[i].data);
}
#endif
}
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
void Kinc_G4_Internal_TextureArraySet(kinc_g4_texture_array_t *array, kinc_g4_texture_unit_t unit) {
#ifdef GL_VERSION_4_2
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
glBindTexture(GL_TEXTURE_2D_ARRAY, array->impl.texture);
#endif
}

View File

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned texture;
} kinc_g4_texture_array_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,304 @@
#include "ogl.h"
#include <kinc/backend/graphics4/shader.h>
#include <kinc/backend/graphics4/vertexbuffer.h>
#include <kinc/graphics4/indexbuffer.h>
#include <kinc/graphics4/vertexbuffer.h>
#include <assert.h>
#include <stdlib.h>
extern kinc_g4_index_buffer_t *Kinc_Internal_CurrentIndexBuffer;
static kinc_g4_vertex_buffer_t *currentVertexBuffer = NULL;
#if defined(KINC_OPENGL_ES) && defined(KINC_ANDROID) && KINC_ANDROID_API >= 18
void *glesVertexAttribDivisor;
#endif
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int vertexCount, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
int instanceDataStepRate) {
buffer->impl.myCount = vertexCount;
buffer->impl.instanceDataStepRate = instanceDataStepRate;
#ifndef NDEBUG
buffer->impl.initialized = false;
#endif
buffer->impl.myStride = 0;
for (int i = 0; i < structure->size; ++i) {
kinc_g4_vertex_element_t element = structure->elements[i];
buffer->impl.myStride += kinc_g4_vertex_data_size(element.data);
}
buffer->impl.structure = *structure;
unsigned gl_usage;
switch (usage) {
case KINC_G4_USAGE_STATIC:
default:
gl_usage = GL_STATIC_DRAW;
break;
case KINC_G4_USAGE_DYNAMIC:
gl_usage = GL_DYNAMIC_DRAW;
break;
case KINC_G4_USAGE_READABLE:
gl_usage = GL_DYNAMIC_DRAW;
break;
}
glGenBuffers(1, &buffer->impl.bufferId);
glCheckErrors();
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
glCheckErrors();
glBufferData(GL_ARRAY_BUFFER, buffer->impl.myStride * buffer->impl.myCount, NULL, gl_usage);
glCheckErrors();
buffer->impl.data = (float *)malloc(vertexCount * buffer->impl.myStride);
}
void Kinc_Internal_G4_VertexBuffer_Unset(kinc_g4_vertex_buffer_t *buffer);
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
Kinc_Internal_G4_VertexBuffer_Unset(buffer);
glDeleteBuffers(1, &buffer->impl.bufferId);
free(buffer->impl.data);
}
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
buffer->impl.sectionStart = 0;
buffer->impl.sectionSize = buffer->impl.myCount * buffer->impl.myStride;
return buffer->impl.data;
}
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
buffer->impl.sectionStart = start * buffer->impl.myStride;
buffer->impl.sectionSize = count * buffer->impl.myStride;
uint8_t *u8data = (uint8_t *)buffer->impl.data;
return (float *)&u8data[buffer->impl.sectionStart];
}
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
glCheckErrors();
uint8_t *u8data = (uint8_t *)buffer->impl.data;
glBufferSubData(GL_ARRAY_BUFFER, buffer->impl.sectionStart, buffer->impl.sectionSize, u8data + buffer->impl.sectionStart);
glCheckErrors();
#ifndef NDEBUG
buffer->impl.initialized = true;
#endif
}
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
glCheckErrors();
uint8_t *u8data = (uint8_t *)buffer->impl.data;
glBufferSubData(GL_ARRAY_BUFFER, buffer->impl.sectionStart, count * buffer->impl.myStride, u8data + buffer->impl.sectionStart);
glCheckErrors();
#ifndef NDEBUG
buffer->impl.initialized = true;
#endif
}
int Kinc_G4_Internal_SetVertexAttributes(kinc_g4_vertex_buffer_t *buffer, int offset);
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
assert(buffer->impl.initialized); // Vertex Buffer is used before lock/unlock was called
int offsetoffset = Kinc_G4_Internal_SetVertexAttributes(buffer, offset);
if (Kinc_Internal_CurrentIndexBuffer != NULL) {
kinc_internal_g4_index_buffer_set(Kinc_Internal_CurrentIndexBuffer);
}
return offsetoffset;
}
void Kinc_Internal_G4_VertexBuffer_Unset(kinc_g4_vertex_buffer_t *buffer) {
if (currentVertexBuffer == buffer) {
currentVertexBuffer = NULL;
}
}
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
return buffer->impl.myCount;
}
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
return buffer->impl.myStride;
}
#if !defined(KINC_OPENGL_ES) || (defined(KINC_OPENGL_ES) && defined(KINC_WASM)) || (defined(KINC_OPENGL_ES) && defined(KINC_ANDROID) && KINC_ANDROID_API >= 18)
static bool attribDivisorUsed = false;
#endif
int Kinc_G4_Internal_SetVertexAttributes(kinc_g4_vertex_buffer_t *buffer, int offset) {
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
glCheckErrors();
int internaloffset = 0;
int actualIndex = 0;
for (int index = 0; index < buffer->impl.structure.size; ++index) {
kinc_g4_vertex_element_t element = buffer->impl.structure.elements[index];
int size = 0;
GLenum type = GL_FLOAT;
switch (element.data) {
case KINC_G4_VERTEX_DATA_NONE:
break;
case KINC_G4_VERTEX_DATA_F32_1X:
size = 1;
break;
case KINC_G4_VERTEX_DATA_F32_2X:
size = 2;
break;
case KINC_G4_VERTEX_DATA_F32_3X:
size = 3;
break;
case KINC_G4_VERTEX_DATA_F32_4X:
size = 4;
break;
case KINC_G4_VERTEX_DATA_F32_4X4:
size = 16;
break;
case KINC_G4_VERTEX_DATA_I8_1X:
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
size = 1;
type = GL_BYTE;
break;
case KINC_G4_VERTEX_DATA_U8_1X:
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
size = 1;
type = GL_UNSIGNED_BYTE;
break;
case KINC_G4_VERTEX_DATA_I8_2X:
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
size = 2;
type = GL_BYTE;
break;
case KINC_G4_VERTEX_DATA_U8_2X:
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
size = 2;
type = GL_UNSIGNED_BYTE;
break;
case KINC_G4_VERTEX_DATA_I8_4X:
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
size = 4;
type = GL_BYTE;
break;
case KINC_G4_VERTEX_DATA_U8_4X:
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
size = 4;
type = GL_UNSIGNED_BYTE;
break;
case KINC_G4_VERTEX_DATA_I16_1X:
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
size = 1;
type = GL_SHORT;
break;
case KINC_G4_VERTEX_DATA_U16_1X:
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
size = 1;
type = GL_UNSIGNED_SHORT;
break;
case KINC_G4_VERTEX_DATA_I16_2X:
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
size = 2;
type = GL_SHORT;
break;
case KINC_G4_VERTEX_DATA_U16_2X:
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
size = 2;
type = GL_UNSIGNED_SHORT;
break;
case KINC_G4_VERTEX_DATA_I16_4X:
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
size = 4;
type = GL_SHORT;
break;
case KINC_G4_VERTEX_DATA_U16_4X:
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
size = 4;
type = GL_UNSIGNED_SHORT;
break;
case KINC_G4_VERTEX_DATA_I32_1X:
size = 1;
type = GL_INT;
break;
case KINC_G4_VERTEX_DATA_U32_1X:
size = 1;
type = GL_UNSIGNED_INT;
break;
case KINC_G4_VERTEX_DATA_I32_2X:
size = 2;
type = GL_INT;
break;
case KINC_G4_VERTEX_DATA_U32_2X:
size = 2;
type = GL_UNSIGNED_INT;
break;
case KINC_G4_VERTEX_DATA_I32_3X:
size = 3;
type = GL_INT;
break;
case KINC_G4_VERTEX_DATA_U32_3X:
size = 3;
type = GL_UNSIGNED_INT;
break;
case KINC_G4_VERTEX_DATA_I32_4X:
size = 4;
type = GL_INT;
break;
case KINC_G4_VERTEX_DATA_U32_4X:
size = 4;
type = GL_UNSIGNED_INT;
break;
}
if (size > 4) {
int subsize = size;
int addonOffset = 0;
while (subsize > 0) {
glEnableVertexAttribArray(offset + actualIndex);
glCheckErrors();
glVertexAttribPointer(offset + actualIndex, 4, type, false, buffer->impl.myStride, (void *)(int64_t)(internaloffset + addonOffset));
glCheckErrors();
#if !defined(KINC_OPENGL_ES) || (defined(KINC_OPENGL_ES) && defined(KINC_WASM))
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
attribDivisorUsed = true;
glVertexAttribDivisor(offset + actualIndex, buffer->impl.instanceDataStepRate);
glCheckErrors();
}
#endif
#if (defined(KINC_OPENGL_ES) && defined(KINC_ANDROID) && KINC_ANDROID_API >= 18)
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
attribDivisorUsed = true;
((void (*)(GLuint, GLuint))glesVertexAttribDivisor)(offset + actualIndex, buffer->impl.instanceDataStepRate);
glCheckErrors();
}
#endif
subsize -= 4;
addonOffset += 4 * 4;
++actualIndex;
}
}
else {
glEnableVertexAttribArray(offset + actualIndex);
glCheckErrors();
glVertexAttribPointer(offset + actualIndex, size, type, type == GL_FLOAT ? false : true, buffer->impl.myStride, (void *)(int64_t)internaloffset);
glCheckErrors();
#if !defined(KINC_OPENGL_ES) || (defined(KINC_OPENGL_ES) && defined(KINC_WASM))
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
attribDivisorUsed = true;
glVertexAttribDivisor(offset + actualIndex, buffer->impl.instanceDataStepRate);
glCheckErrors();
}
#endif
#if (defined(KINC_OPENGL_ES) && defined(KINC_ANDROID) && KINC_ANDROID_API >= 18)
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
attribDivisorUsed = true;
((void (*)(GLuint, GLuint))glesVertexAttribDivisor)(offset + actualIndex, buffer->impl.instanceDataStepRate);
glCheckErrors();
}
#endif
++actualIndex;
}
internaloffset += kinc_g4_vertex_data_size(element.data);
}
int count = kinc_internal_opengl_max_vertex_attribute_arrays - offset;
for (int index = actualIndex; index < count; ++index) {
glDisableVertexAttribArray(offset + index);
glCheckErrors();
}
return actualIndex;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <kinc/graphics4/vertexstructure.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
float *data;
int myCount;
int myStride;
unsigned bufferId;
int sectionStart;
int sectionSize;
// #if defined KINC_ANDROID || defined KINC_EMSCRIPTEN
kinc_g4_vertex_structure_t structure;
// #endif
int instanceDataStepRate;
#ifndef NDEBUG
bool initialized;
#endif
} kinc_g4_vertex_buffer_impl_t;
#ifdef __cplusplus
}
#endif