forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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;
|
@ -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
|
@ -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
|
||||
}
|
@ -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;
|
@ -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
|
@ -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
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "TextureImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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"
|
@ -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;
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned texture;
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -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;
|
||||
}
|
@ -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
|
Reference in New Issue
Block a user