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

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