Fully working PBR renderer
This commit is contained in:
parent
d54ecc33da
commit
897dd94c24
@ -32,22 +32,22 @@ IDLE_RPM = 800
|
||||
REDLINE_RPM = 6000
|
||||
|
||||
# Engine dynamics (in rpm/sec)
|
||||
THROTTLE_RPM_RATE = 800 # When throttle is pressed, engine spins up
|
||||
THROTTLE_RPM_RATE = 8000 # When throttle is pressed, engine spins up
|
||||
BRAKE_RPM_RATE = 2500 # When braking, engine RPM drops rapidly
|
||||
DAMPING_FACTOR = 5 # How strongly engine RPM is forced toward the "ideal" RPM
|
||||
DAMPING_FACTOR = 1 # How strongly engine RPM is forced toward the "ideal" RPM
|
||||
|
||||
# These dynamics model the connection between engine torque and vehicle acceleration:
|
||||
# The vehicle's acceleration (in mph/s) is proportional to the difference between the
|
||||
# current engine RPM and the ideal RPM that would be produced by the current speed in the given gear.
|
||||
ACCELERATION_CONVERSION = 150 # (rpm difference) to mph/s conversion factor
|
||||
ACCELERATION_CONVERSION = 10 # (rpm difference) to mph/s conversion factor
|
||||
DRAG_COEFF = 0.02 # Drag (per second) that always slows the vehicle
|
||||
|
||||
# Conversion constant (empirical) for what engine RPM should be for a given vehicle speed
|
||||
# in a particular gear. In this model, ideal_rpm = speed × gear_ratio × K.
|
||||
K = 21
|
||||
K = 0.1
|
||||
|
||||
# Maximum vehicle speed (in mph)
|
||||
MAX_SPEED = 90
|
||||
MAX_SPEED = 9000000
|
||||
|
||||
# ----- Transmission & Gear Ratios -----
|
||||
# These gear ratios (including reverse = gear 0) are assumed to incorporate the effect
|
||||
@ -114,6 +114,16 @@ def point_line_distance(P, A, B):
|
||||
proj = (A[0] + t*AB[0], A[1] + t*AB[1])
|
||||
return math.hypot(P[0] - proj[0], P[1] - proj[1])
|
||||
|
||||
def closest_point_on_segment(P, A, B):
|
||||
"""Return the closest point on line segment AB to point P."""
|
||||
AB = (B[0] - A[0], B[1] - A[1])
|
||||
AP = (P[0] - A[0], P[1] - A[1])
|
||||
ab2 = AB[0]**2 + AB[1]**2
|
||||
if ab2 == 0:
|
||||
return A
|
||||
t = max(0, min(1, (AP[0]*AB[0] + AP[1]*AB[1]) / ab2))
|
||||
return (A[0] + t * AB[0], A[1] + t * AB[1])
|
||||
|
||||
# ----- Game Objects -----
|
||||
class Car:
|
||||
def __init__(self):
|
||||
@ -136,7 +146,6 @@ class Car:
|
||||
ideal_rpm = max(IDLE_RPM, self.speed * GEAR_RATIOS[self.gear] * K)
|
||||
|
||||
# --- Engine RPM Dynamics ---
|
||||
# Throttle increases engine RPM; braking drops it.
|
||||
throttle_effect = THROTTLE_RPM_RATE if throttle else 0
|
||||
brake_effect = BRAKE_RPM_RATE if brake else 0
|
||||
# Engine tends to return toward the ideal RPM.
|
||||
@ -149,12 +158,8 @@ class Car:
|
||||
self.engine_rpm = REDLINE_RPM
|
||||
|
||||
# --- Vehicle Acceleration Dynamics ---
|
||||
# The acceleration is proportional to how much the engine is "over-revving" relative to ideal.
|
||||
# A positive difference means extra torque; a negative difference means the engine is not producing enough torque.
|
||||
accel = (self.engine_rpm - ideal_rpm) / ACCELERATION_CONVERSION
|
||||
# Subtract drag proportional to speed.
|
||||
accel -= DRAG_COEFF * self.speed
|
||||
# Update vehicle speed.
|
||||
self.speed += accel * dt
|
||||
if self.speed < 0:
|
||||
self.speed = 0
|
||||
@ -162,16 +167,13 @@ class Car:
|
||||
self.speed = MAX_SPEED
|
||||
|
||||
# --- Update Position ---
|
||||
# When in reverse (gear 0), the vehicle moves backward.
|
||||
direction = 1 if self.gear != 0 else -1
|
||||
# Convert speed (mph) to distance per second. (1 mph ≈ 1.46667 ft/s)
|
||||
ft_per_sec = self.speed * 1.46667
|
||||
ft_per_sec = self.speed * 1.46667 # Convert mph to ft/s
|
||||
self.x += math.cos(self.angle) * ft_per_sec * dt * direction
|
||||
self.y += math.sin(self.angle) * ft_per_sec * dt * direction
|
||||
|
||||
def rev_match_on_shift_up(self):
|
||||
"""Simulate a realistic drop in RPM when upshifting (rev-match)."""
|
||||
# On an upshift, the engine RPM typically drops by 10–20%.
|
||||
self.engine_rpm *= 0.85
|
||||
if self.engine_rpm < IDLE_RPM:
|
||||
self.engine_rpm = IDLE_RPM
|
||||
@ -237,7 +239,6 @@ def draw_road(surface, track, offset_x, offset_y, road_width):
|
||||
seg_len = math.hypot(dx, dy)
|
||||
if seg_len == 0:
|
||||
continue
|
||||
# Compute a perpendicular vector.
|
||||
nx = -dy / seg_len
|
||||
ny = dx / seg_len
|
||||
half_w = road_width / 2
|
||||
@ -252,7 +253,6 @@ def draw_road(surface, track, offset_x, offset_y, road_width):
|
||||
(int(start_right[0] + offset_x), int(start_right[1] + offset_y))
|
||||
]
|
||||
pygame.draw.polygon(surface, (100, 100, 100), poly)
|
||||
# Draw a center line for visual effect.
|
||||
center_start = (start[0] + offset_x, start[1] + offset_y)
|
||||
center_end = (end[0] + offset_x, end[1] + offset_y)
|
||||
pygame.draw.line(surface, (255, 255, 255), center_start, center_end, 2)
|
||||
@ -264,7 +264,6 @@ def draw_car(surface, car, offset_x, offset_y):
|
||||
center = (car.x + offset_x, car.y + offset_y)
|
||||
half_length = 40 / 2
|
||||
half_width = 20 / 2
|
||||
# Define a 5-point polygon for the car shape.
|
||||
points = [
|
||||
( half_length, 0), # Front tip
|
||||
( half_length * 0.2, -half_width), # Rear top
|
||||
@ -279,6 +278,66 @@ def draw_car(surface, car, offset_x, offset_y):
|
||||
pygame.draw.polygon(surface, (255, 0, 0), rotated)
|
||||
pygame.draw.polygon(surface, (255, 255, 255), rotated, 2)
|
||||
|
||||
def draw_map_view(surface, track, car):
|
||||
"""
|
||||
Draw a mini-map in the bottom-right corner displaying all generated road segments
|
||||
and the car's current position.
|
||||
"""
|
||||
map_width = 200
|
||||
map_height = 150
|
||||
map_x = SCREEN_WIDTH - map_width - 10
|
||||
map_y = SCREEN_HEIGHT - map_height - 10
|
||||
map_rect = pygame.Rect(map_x, map_y, map_width, map_height)
|
||||
|
||||
# Draw mini-map background and border
|
||||
pygame.draw.rect(surface, (30, 30, 30), map_rect)
|
||||
pygame.draw.rect(surface, (255, 255, 255), map_rect, 2)
|
||||
|
||||
# Compute bounding box for all track segments
|
||||
if track.segments:
|
||||
xs = []
|
||||
ys = []
|
||||
for seg in track.segments:
|
||||
A, B = seg
|
||||
xs.extend([A[0], B[0]])
|
||||
ys.extend([A[1], B[1]])
|
||||
min_x, max_x = min(xs), max(xs)
|
||||
min_y, max_y = min(ys), max(ys)
|
||||
else:
|
||||
min_x, max_x, min_y, max_y = 0, 1, 0, 1
|
||||
|
||||
# Add margins
|
||||
margin = 10
|
||||
min_x -= margin
|
||||
min_y -= margin
|
||||
max_x += margin
|
||||
max_y += margin
|
||||
|
||||
world_width = max_x - min_x
|
||||
world_height = max_y - min_y
|
||||
if world_width == 0 or world_height == 0:
|
||||
scale = 1
|
||||
else:
|
||||
scale = min((map_width - 20) / world_width, (map_height - 20) / world_height)
|
||||
|
||||
# Convert world coordinates to mini-map coordinates
|
||||
def world_to_map(pos):
|
||||
world_x, world_y = pos
|
||||
map_pos_x = map_x + 10 + (world_x - min_x) * scale
|
||||
map_pos_y = map_y + 10 + (world_y - min_y) * scale
|
||||
return (int(map_pos_x), int(map_pos_y))
|
||||
|
||||
# Draw road segments on mini-map
|
||||
for seg in track.segments:
|
||||
A, B = seg
|
||||
map_A = world_to_map(A)
|
||||
map_B = world_to_map(B)
|
||||
pygame.draw.line(surface, (200, 200, 200), map_A, map_B, 2)
|
||||
|
||||
# Draw the car's current position as a small circle
|
||||
car_map_pos = world_to_map((car.x, car.y))
|
||||
pygame.draw.circle(surface, (255, 0, 0), car_map_pos, 4)
|
||||
|
||||
# ----- Main Game Loop -----
|
||||
def main():
|
||||
pygame.init()
|
||||
@ -299,18 +358,12 @@ def main():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.KEYDOWN:
|
||||
# Upshift (E)
|
||||
if event.key == pygame.K_e and car.gear < 10:
|
||||
old_ratio = GEAR_RATIOS[car.gear]
|
||||
car.gear += 1
|
||||
# Rev-match on upshift: drop RPM to roughly maintain consistency.
|
||||
car.rev_match_on_shift_up()
|
||||
# Downshift (Q), but do not downshift below gear 1.
|
||||
elif event.key == pygame.K_q and car.gear > 1:
|
||||
old_ratio = GEAR_RATIOS[car.gear]
|
||||
car.gear -= 1
|
||||
car.rev_match_on_shift_down()
|
||||
# Toggle reverse (R)
|
||||
elif event.key == pygame.K_r:
|
||||
if car.gear == 0:
|
||||
car.gear = 1
|
||||
@ -330,7 +383,7 @@ def main():
|
||||
car.update(throttle, brake, dt)
|
||||
track.ensure_track_length((car.x, car.y), min_distance=500)
|
||||
|
||||
# Determine the view offset so the car is centered.
|
||||
# Determine view offset to center the car.
|
||||
offset_x = SCREEN_WIDTH / 2 - car.x
|
||||
offset_y = SCREEN_HEIGHT / 2 - car.y
|
||||
|
||||
@ -344,17 +397,35 @@ def main():
|
||||
status_surf = font.render(status_text, True, (255, 255, 255))
|
||||
screen.blit(status_surf, (10, 10))
|
||||
|
||||
# If off road, draw blue line to nearest point on road.
|
||||
if not is_on_road(car, track, ROAD_WIDTH):
|
||||
P = (car.x, car.y)
|
||||
min_distance = float('inf')
|
||||
closest_point = None
|
||||
for seg in track.segments:
|
||||
A, B = seg
|
||||
candidate = closest_point_on_segment(P, A, B)
|
||||
d = math.hypot(P[0] - candidate[0], P[1] - candidate[1])
|
||||
if d < min_distance:
|
||||
min_distance = d
|
||||
closest_point = candidate
|
||||
if closest_point is not None:
|
||||
start_screen = (int(car.x + offset_x), int(car.y + offset_y))
|
||||
end_screen = (int(closest_point[0] + offset_x), int(closest_point[1] + offset_y))
|
||||
pygame.draw.line(screen, (0, 0, 255), start_screen, end_screen, 2)
|
||||
|
||||
# Draw gauges.
|
||||
# Speed gauge shows vehicle speed in mph.
|
||||
draw_gauge(screen, SPEED_GAUGE_CENTER, GAUGE_RADIUS, 0, MAX_SPEED, car.speed, "Speed (mph)")
|
||||
# Tachometer shows engine RPM.
|
||||
draw_gauge(screen, TACH_GAUGE_CENTER, GAUGE_RADIUS, 0, REDLINE_RPM, car.engine_rpm, "RPM")
|
||||
|
||||
# Display current gear.
|
||||
# Display gear information.
|
||||
gear_text = "Reverse" if (car.gear == 0) else f"Gear: {car.gear}"
|
||||
gear_surf = font.render(gear_text, True, (255, 255, 255))
|
||||
screen.blit(gear_surf, (SPEED_GAUGE_CENTER[0] - GAUGE_RADIUS, SPEED_GAUGE_CENTER[1] + GAUGE_RADIUS + 40))
|
||||
|
||||
# ----- Draw Map View -----
|
||||
draw_map_view(screen, track, car)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
pygame.quit()
|
||||
|
29
physicaly-based-renderer/Makefile
Normal file
29
physicaly-based-renderer/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
# Compiler settings
|
||||
CXX = g++
|
||||
CXXFLAGS = -std=c++20 -I. -Iinclude -Iimgui-docking -IC:/msys64/mingw64/include -DGLEW_STATIC -g
|
||||
LDFLAGS = -LC:/msys64/mingw64/lib -lglfw3 -lopengl32 -lgdi32 -lglew32 -lglu32 -lyaml-cpp
|
||||
|
||||
# List ImGui source files
|
||||
IMGUISRCS = imgui-docking/imgui.cpp \
|
||||
imgui-docking/imgui_demo.cpp \
|
||||
imgui-docking/imgui_draw.cpp \
|
||||
imgui-docking/imgui_tables.cpp \
|
||||
imgui-docking/imgui_widgets.cpp \
|
||||
imgui-docking/imgui_impl_glfw.cpp \
|
||||
imgui-docking/imgui_impl_opengl3.cpp
|
||||
|
||||
# List all source files
|
||||
SRCS = main.cpp $(IMGUISRCS)
|
||||
OBJS = $(SRCS:.cpp=.o)
|
||||
TARGET = main
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET)
|
21
physicaly-based-renderer/imgui-docking/LICENSE.txt
Normal file
21
physicaly-based-renderer/imgui-docking/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2025 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
141
physicaly-based-renderer/imgui-docking/imconfig.h
Normal file
141
physicaly-based-renderer/imgui-docking/imconfig.h
Normal file
@ -0,0 +1,141 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||
//-----------------------------------------------------------------------------
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
|
||||
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
|
||||
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
|
||||
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert.
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Enable Test Engine / Automation features.
|
||||
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
||||
|
||||
//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
|
||||
//#define IMGUI_USE_LEGACY_CRC32_ADLER
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
//#define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
|
||||
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
||||
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
//struct ImDrawCmd;
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||
}
|
||||
*/
|
22948
physicaly-based-renderer/imgui-docking/imgui.cpp
Normal file
22948
physicaly-based-renderer/imgui-docking/imgui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4033
physicaly-based-renderer/imgui-docking/imgui.h
Normal file
4033
physicaly-based-renderer/imgui-docking/imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
BIN
physicaly-based-renderer/imgui-docking/imgui.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui.o
Normal file
Binary file not shown.
10984
physicaly-based-renderer/imgui-docking/imgui_demo.cpp
Normal file
10984
physicaly-based-renderer/imgui-docking/imgui_demo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
physicaly-based-renderer/imgui-docking/imgui_demo.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui_demo.o
Normal file
Binary file not shown.
4857
physicaly-based-renderer/imgui-docking/imgui_draw.cpp
Normal file
4857
physicaly-based-renderer/imgui-docking/imgui_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
physicaly-based-renderer/imgui-docking/imgui_draw.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui_draw.o
Normal file
Binary file not shown.
1460
physicaly-based-renderer/imgui-docking/imgui_impl_glfw.cpp
Normal file
1460
physicaly-based-renderer/imgui-docking/imgui_impl_glfw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
69
physicaly-based-renderer/imgui-docking/imgui_impl_glfw.h
Normal file
69
physicaly-based-renderer/imgui-docking/imgui_impl_glfw.h
Normal file
@ -0,0 +1,69 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct GLFWwindow;
|
||||
struct GLFWmonitor;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||
#ifdef __EMSCRIPTEN__
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
|
||||
//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
|
||||
#endif
|
||||
|
||||
// GLFW callbacks install
|
||||
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
|
||||
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
|
||||
|
||||
// GFLW callbacks options:
|
||||
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
|
||||
|
||||
// GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||
|
||||
// GLFW helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
BIN
physicaly-based-renderer/imgui-docking/imgui_impl_glfw.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui_impl_glfw.o
Normal file
Binary file not shown.
1023
physicaly-based-renderer/imgui-docking/imgui_impl_opengl3.cpp
Normal file
1023
physicaly-based-renderer/imgui-docking/imgui_impl_opengl3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
67
physicaly-based-renderer/imgui-docking/imgui_impl_opengl3.h
Normal file
67
physicaly-based-renderer/imgui-docking/imgui_impl_opengl3.h
Normal file
@ -0,0 +1,67 @@
|
||||
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
|
||||
// - Desktop GL: 2.x 3.x 4.x
|
||||
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
// - This is done automatically on iOS, Android and Emscripten targets.
|
||||
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// About GLSL version:
|
||||
// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
|
||||
// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
|
||||
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// (Optional) Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
// Configuration flags to add in your imconfig file:
|
||||
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
|
||||
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
|
||||
|
||||
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
|
||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
|
||||
// Try to detect GLES on matching platforms
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
|
||||
#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
|
||||
#elif defined(__EMSCRIPTEN__) || defined(__amigaos4__)
|
||||
#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
|
||||
#else
|
||||
// Otherwise imgui_impl_opengl3_loader.h will be used.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
BIN
physicaly-based-renderer/imgui-docking/imgui_impl_opengl3.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui_impl_opengl3.o
Normal file
Binary file not shown.
@ -0,0 +1,916 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// About imgui_impl_opengl3_loader.h:
|
||||
//
|
||||
// We embed our own OpenGL loader to not require user to provide their own or to have to use ours,
|
||||
// which proved to be endless problems for users.
|
||||
// Our loader is custom-generated, based on gl3w but automatically filtered to only include
|
||||
// enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small.
|
||||
//
|
||||
// YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY.
|
||||
// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
|
||||
//
|
||||
// IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions):
|
||||
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCLUDING 'imgui_impl_opengl3_loader.h'
|
||||
// IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER.
|
||||
// (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS)
|
||||
// YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT.
|
||||
// BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp
|
||||
// WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT.
|
||||
//
|
||||
// Regenerate with:
|
||||
// python3 gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
|
||||
//
|
||||
// More info:
|
||||
// https://github.com/dearimgui/gl3w_stripped
|
||||
// https://github.com/ocornut/imgui/issues/4445
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* This file was generated with gl3w_gen.py, part of imgl3w
|
||||
* (hosted at https://github.com/dearimgui/gl3w_stripped)
|
||||
*
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
*
|
||||
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
* distribute this software, either in source code form or as a compiled
|
||||
* binary, for any purpose, commercial or non-commercial, and by any
|
||||
* means.
|
||||
*
|
||||
* In jurisdictions that recognize copyright laws, the author or authors
|
||||
* of this software dedicate any and all copyright interest in the
|
||||
* software to the public domain. We make this dedication for the benefit
|
||||
* of the public at large and to the detriment of our heirs and
|
||||
* successors. We intend this dedication to be an overt act of
|
||||
* relinquishment in perpetuity of all present and future rights to this
|
||||
* software under copyright law.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __gl3w_h_
|
||||
#define __gl3w_h_
|
||||
|
||||
// Adapted from KHR/khrplatform.h to avoid including entire file.
|
||||
#ifndef __khrplatform_h_
|
||||
typedef float khronos_float_t;
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
#ifdef _WIN64
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef signed long int khronos_ssize_t;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
typedef signed __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
|
||||
#include <stdint.h>
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#else
|
||||
typedef signed long long khronos_int64_t;
|
||||
typedef unsigned long long khronos_uint64_t;
|
||||
#endif
|
||||
#endif // __khrplatform_h_
|
||||
|
||||
#ifndef __gl_glcorearb_h_
|
||||
#define __gl_glcorearb_h_ 1
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
** Copyright 2013-2020 The Khronos Group Inc.
|
||||
** SPDX-License-Identifier: MIT
|
||||
**
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** https://github.com/KhronosGroup/OpenGL-Registry
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#ifndef APIENTRYP
|
||||
#define APIENTRYP APIENTRY *
|
||||
#endif
|
||||
#ifndef GLAPI
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
/* glcorearb.h is for use with OpenGL core profile implementations.
|
||||
** It should should be placed in the same directory as gl.h and
|
||||
** included as <GL/glcorearb.h>.
|
||||
**
|
||||
** glcorearb.h includes only APIs in the latest OpenGL core profile
|
||||
** implementation together with APIs in newer ARB extensions which
|
||||
** can be supported by the core profile. It does not, and never will
|
||||
** include functionality removed from the core profile, such as
|
||||
** fixed-function vertex and fragment processing.
|
||||
**
|
||||
** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or
|
||||
** <GL/glext.h> in the same source file.
|
||||
*/
|
||||
/* Generated C header for:
|
||||
* API: gl
|
||||
* Profile: core
|
||||
* Versions considered: .*
|
||||
* Versions emitted: .*
|
||||
* Default extensions included: glcore
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
#ifndef GL_VERSION_1_0
|
||||
typedef void GLvoid;
|
||||
typedef unsigned int GLenum;
|
||||
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef double GLdouble;
|
||||
typedef unsigned int GLuint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
#define GL_POLYGON_MODE 0x0B40
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_STENCIL_TEST 0x0B90
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_FILL 0x1B02
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_REPEAT 0x2901
|
||||
typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
|
||||
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
|
||||
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
|
||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
|
||||
typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
|
||||
GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GLAPI void APIENTRY glClear (GLbitfield mask);
|
||||
GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GLAPI void APIENTRY glDisable (GLenum cap);
|
||||
GLAPI void APIENTRY glEnable (GLenum cap);
|
||||
GLAPI void APIENTRY glFlush (void);
|
||||
GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
GLAPI GLenum APIENTRY glGetError (void);
|
||||
GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);
|
||||
GLAPI const GLubyte *APIENTRY glGetString (GLenum name);
|
||||
GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
|
||||
GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_0 */
|
||||
#ifndef GL_VERSION_1_1
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef double GLclampd;
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_1 */
|
||||
#ifndef GL_VERSION_1_2
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#endif /* GL_VERSION_1_2 */
|
||||
#ifndef GL_VERSION_1_3
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glActiveTexture (GLenum texture);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_3 */
|
||||
#ifndef GL_VERSION_1_4
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
#define GL_BLEND_SRC_ALPHA 0x80CB
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
GLAPI void APIENTRY glBlendEquation (GLenum mode);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_4 */
|
||||
#ifndef GL_VERSION_1_5
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_5 */
|
||||
#ifndef GL_VERSION_2_0
|
||||
typedef char GLchar;
|
||||
typedef khronos_int16_t GLshort;
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef khronos_uint16_t GLushort;
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
#define GL_UPPER_LEFT 0x8CA2
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
|
||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
|
||||
typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GLAPI void APIENTRY glCompileShader (GLuint shader);
|
||||
GLAPI GLuint APIENTRY glCreateProgram (void);
|
||||
GLAPI GLuint APIENTRY glCreateShader (GLenum type);
|
||||
GLAPI void APIENTRY glDeleteProgram (GLuint program);
|
||||
GLAPI void APIENTRY glDeleteShader (GLuint shader);
|
||||
GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
|
||||
GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
|
||||
GLAPI void APIENTRY glLinkProgram (GLuint program);
|
||||
GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
GLAPI void APIENTRY glUseProgram (GLuint program);
|
||||
GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
|
||||
GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
#endif
|
||||
#endif /* GL_VERSION_2_0 */
|
||||
#ifndef GL_VERSION_2_1
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
|
||||
#endif /* GL_VERSION_2_1 */
|
||||
#ifndef GL_VERSION_3_0
|
||||
typedef khronos_uint16_t GLhalf;
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
#define GL_FRAMEBUFFER_SRGB 0x8DB9
|
||||
#define GL_VERTEX_ARRAY_BINDING 0x85B5
|
||||
typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
|
||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
|
||||
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
|
||||
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
|
||||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
|
||||
GLAPI void APIENTRY glBindVertexArray (GLuint array);
|
||||
GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
|
||||
GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_0 */
|
||||
#ifndef GL_VERSION_3_1
|
||||
#define GL_VERSION_3_1 1
|
||||
#define GL_PRIMITIVE_RESTART 0x8F9D
|
||||
#endif /* GL_VERSION_3_1 */
|
||||
#ifndef GL_VERSION_3_2
|
||||
#define GL_VERSION_3_2 1
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef khronos_uint64_t GLuint64;
|
||||
typedef khronos_int64_t GLint64;
|
||||
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
|
||||
#define GL_CONTEXT_PROFILE_MASK 0x9126
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_2 */
|
||||
#ifndef GL_VERSION_3_3
|
||||
#define GL_VERSION_3_3 1
|
||||
#define GL_SAMPLER_BINDING 0x8919
|
||||
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_3 */
|
||||
#ifndef GL_VERSION_4_1
|
||||
typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
|
||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
|
||||
#endif /* GL_VERSION_4_1 */
|
||||
#ifndef GL_VERSION_4_3
|
||||
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
|
||||
#endif /* GL_VERSION_4_3 */
|
||||
#ifndef GL_VERSION_4_5
|
||||
#define GL_CLIP_ORIGIN 0x935C
|
||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
|
||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
|
||||
#endif /* GL_VERSION_4_5 */
|
||||
#ifndef GL_ARB_bindless_texture
|
||||
typedef khronos_uint64_t GLuint64EXT;
|
||||
#endif /* GL_ARB_bindless_texture */
|
||||
#ifndef GL_ARB_cl_event
|
||||
struct _cl_context;
|
||||
struct _cl_event;
|
||||
#endif /* GL_ARB_cl_event */
|
||||
#ifndef GL_ARB_clip_control
|
||||
#define GL_ARB_clip_control 1
|
||||
#endif /* GL_ARB_clip_control */
|
||||
#ifndef GL_ARB_debug_output
|
||||
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
|
||||
#endif /* GL_ARB_debug_output */
|
||||
#ifndef GL_EXT_EGL_image_storage
|
||||
typedef void *GLeglImageOES;
|
||||
#endif /* GL_EXT_EGL_image_storage */
|
||||
#ifndef GL_EXT_direct_state_access
|
||||
typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
|
||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
|
||||
typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
|
||||
#endif /* GL_EXT_direct_state_access */
|
||||
#ifndef GL_NV_draw_vulkan_image
|
||||
typedef void (APIENTRY *GLVULKANPROCNV)(void);
|
||||
#endif /* GL_NV_draw_vulkan_image */
|
||||
#ifndef GL_NV_gpu_shader5
|
||||
typedef khronos_int64_t GLint64EXT;
|
||||
#endif /* GL_NV_gpu_shader5 */
|
||||
#ifndef GL_NV_vertex_buffer_unified_memory
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
|
||||
#endif /* GL_NV_vertex_buffer_unified_memory */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GL3W_API
|
||||
#define GL3W_API
|
||||
#endif
|
||||
|
||||
#ifndef __gl_h_
|
||||
#define __gl_h_
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GL3W_OK 0
|
||||
#define GL3W_ERROR_INIT -1
|
||||
#define GL3W_ERROR_LIBRARY_OPEN -2
|
||||
#define GL3W_ERROR_OPENGL_VERSION -3
|
||||
|
||||
typedef void (*GL3WglProc)(void);
|
||||
typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
|
||||
|
||||
/* gl3w api */
|
||||
GL3W_API int imgl3wInit(void);
|
||||
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
|
||||
GL3W_API int imgl3wIsSupported(int major, int minor);
|
||||
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
|
||||
|
||||
/* gl3w internal state */
|
||||
union ImGL3WProcs {
|
||||
GL3WglProc ptr[59];
|
||||
struct {
|
||||
PFNGLACTIVETEXTUREPROC ActiveTexture;
|
||||
PFNGLATTACHSHADERPROC AttachShader;
|
||||
PFNGLBINDBUFFERPROC BindBuffer;
|
||||
PFNGLBINDSAMPLERPROC BindSampler;
|
||||
PFNGLBINDTEXTUREPROC BindTexture;
|
||||
PFNGLBINDVERTEXARRAYPROC BindVertexArray;
|
||||
PFNGLBLENDEQUATIONPROC BlendEquation;
|
||||
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
|
||||
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
|
||||
PFNGLBUFFERDATAPROC BufferData;
|
||||
PFNGLBUFFERSUBDATAPROC BufferSubData;
|
||||
PFNGLCLEARPROC Clear;
|
||||
PFNGLCLEARCOLORPROC ClearColor;
|
||||
PFNGLCOMPILESHADERPROC CompileShader;
|
||||
PFNGLCREATEPROGRAMPROC CreateProgram;
|
||||
PFNGLCREATESHADERPROC CreateShader;
|
||||
PFNGLDELETEBUFFERSPROC DeleteBuffers;
|
||||
PFNGLDELETEPROGRAMPROC DeleteProgram;
|
||||
PFNGLDELETESHADERPROC DeleteShader;
|
||||
PFNGLDELETETEXTURESPROC DeleteTextures;
|
||||
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
|
||||
PFNGLDETACHSHADERPROC DetachShader;
|
||||
PFNGLDISABLEPROC Disable;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
|
||||
PFNGLDRAWELEMENTSPROC DrawElements;
|
||||
PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;
|
||||
PFNGLENABLEPROC Enable;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
|
||||
PFNGLFLUSHPROC Flush;
|
||||
PFNGLGENBUFFERSPROC GenBuffers;
|
||||
PFNGLGENTEXTURESPROC GenTextures;
|
||||
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
|
||||
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
|
||||
PFNGLGETERRORPROC GetError;
|
||||
PFNGLGETINTEGERVPROC GetIntegerv;
|
||||
PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;
|
||||
PFNGLGETPROGRAMIVPROC GetProgramiv;
|
||||
PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;
|
||||
PFNGLGETSHADERIVPROC GetShaderiv;
|
||||
PFNGLGETSTRINGPROC GetString;
|
||||
PFNGLGETSTRINGIPROC GetStringi;
|
||||
PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
|
||||
PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv;
|
||||
PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv;
|
||||
PFNGLISENABLEDPROC IsEnabled;
|
||||
PFNGLISPROGRAMPROC IsProgram;
|
||||
PFNGLLINKPROGRAMPROC LinkProgram;
|
||||
PFNGLPIXELSTOREIPROC PixelStorei;
|
||||
PFNGLPOLYGONMODEPROC PolygonMode;
|
||||
PFNGLREADPIXELSPROC ReadPixels;
|
||||
PFNGLSCISSORPROC Scissor;
|
||||
PFNGLSHADERSOURCEPROC ShaderSource;
|
||||
PFNGLTEXIMAGE2DPROC TexImage2D;
|
||||
PFNGLTEXPARAMETERIPROC TexParameteri;
|
||||
PFNGLUNIFORM1IPROC Uniform1i;
|
||||
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
|
||||
PFNGLUSEPROGRAMPROC UseProgram;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
|
||||
PFNGLVIEWPORTPROC Viewport;
|
||||
} gl;
|
||||
};
|
||||
|
||||
GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
||||
|
||||
/* OpenGL functions */
|
||||
#define glActiveTexture imgl3wProcs.gl.ActiveTexture
|
||||
#define glAttachShader imgl3wProcs.gl.AttachShader
|
||||
#define glBindBuffer imgl3wProcs.gl.BindBuffer
|
||||
#define glBindSampler imgl3wProcs.gl.BindSampler
|
||||
#define glBindTexture imgl3wProcs.gl.BindTexture
|
||||
#define glBindVertexArray imgl3wProcs.gl.BindVertexArray
|
||||
#define glBlendEquation imgl3wProcs.gl.BlendEquation
|
||||
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
|
||||
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
|
||||
#define glBufferData imgl3wProcs.gl.BufferData
|
||||
#define glBufferSubData imgl3wProcs.gl.BufferSubData
|
||||
#define glClear imgl3wProcs.gl.Clear
|
||||
#define glClearColor imgl3wProcs.gl.ClearColor
|
||||
#define glCompileShader imgl3wProcs.gl.CompileShader
|
||||
#define glCreateProgram imgl3wProcs.gl.CreateProgram
|
||||
#define glCreateShader imgl3wProcs.gl.CreateShader
|
||||
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
|
||||
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
|
||||
#define glDeleteShader imgl3wProcs.gl.DeleteShader
|
||||
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
|
||||
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
|
||||
#define glDetachShader imgl3wProcs.gl.DetachShader
|
||||
#define glDisable imgl3wProcs.gl.Disable
|
||||
#define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray
|
||||
#define glDrawElements imgl3wProcs.gl.DrawElements
|
||||
#define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex
|
||||
#define glEnable imgl3wProcs.gl.Enable
|
||||
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
|
||||
#define glFlush imgl3wProcs.gl.Flush
|
||||
#define glGenBuffers imgl3wProcs.gl.GenBuffers
|
||||
#define glGenTextures imgl3wProcs.gl.GenTextures
|
||||
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
|
||||
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
|
||||
#define glGetError imgl3wProcs.gl.GetError
|
||||
#define glGetIntegerv imgl3wProcs.gl.GetIntegerv
|
||||
#define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog
|
||||
#define glGetProgramiv imgl3wProcs.gl.GetProgramiv
|
||||
#define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog
|
||||
#define glGetShaderiv imgl3wProcs.gl.GetShaderiv
|
||||
#define glGetString imgl3wProcs.gl.GetString
|
||||
#define glGetStringi imgl3wProcs.gl.GetStringi
|
||||
#define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation
|
||||
#define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv
|
||||
#define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv
|
||||
#define glIsEnabled imgl3wProcs.gl.IsEnabled
|
||||
#define glIsProgram imgl3wProcs.gl.IsProgram
|
||||
#define glLinkProgram imgl3wProcs.gl.LinkProgram
|
||||
#define glPixelStorei imgl3wProcs.gl.PixelStorei
|
||||
#define glPolygonMode imgl3wProcs.gl.PolygonMode
|
||||
#define glReadPixels imgl3wProcs.gl.ReadPixels
|
||||
#define glScissor imgl3wProcs.gl.Scissor
|
||||
#define glShaderSource imgl3wProcs.gl.ShaderSource
|
||||
#define glTexImage2D imgl3wProcs.gl.TexImage2D
|
||||
#define glTexParameteri imgl3wProcs.gl.TexParameteri
|
||||
#define glUniform1i imgl3wProcs.gl.Uniform1i
|
||||
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
|
||||
#define glUseProgram imgl3wProcs.gl.UseProgram
|
||||
#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer
|
||||
#define glViewport imgl3wProcs.gl.Viewport
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef IMGL3W_IMPL
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GL3W_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
static HMODULE libgl;
|
||||
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
|
||||
static GL3WglGetProcAddr wgl_get_proc_address;
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = LoadLibraryA("opengl32.dll");
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { FreeLibrary(libgl); }
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
res = (GL3WglProc)wgl_get_proc_address(proc);
|
||||
if (!res)
|
||||
res = (GL3WglProc)GetProcAddress(libgl, proc);
|
||||
return res;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *libgl;
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { dlclose(libgl); }
|
||||
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
*(void **)(&res) = dlsym(libgl, proc);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void* libgl; // OpenGL library
|
||||
static void* libglx; // GLX library
|
||||
static void* libegl; // EGL library
|
||||
static GL3WGetProcAddressProc gl_get_proc_address;
|
||||
|
||||
static void close_libgl(void)
|
||||
{
|
||||
if (libgl) {
|
||||
dlclose(libgl);
|
||||
libgl = NULL;
|
||||
}
|
||||
if (libegl) {
|
||||
dlclose(libegl);
|
||||
libegl = NULL;
|
||||
}
|
||||
if (libglx) {
|
||||
dlclose(libglx);
|
||||
libglx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_library_loaded(const char* name, void** lib)
|
||||
{
|
||||
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||
return *lib != NULL;
|
||||
}
|
||||
|
||||
static int open_libs(void)
|
||||
{
|
||||
// On Linux we have two APIs to get process addresses: EGL and GLX.
|
||||
// EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
|
||||
|
||||
libgl = NULL;
|
||||
libegl = NULL;
|
||||
libglx = NULL;
|
||||
|
||||
// First check what's already loaded, the windowing library might have
|
||||
// already loaded either EGL or GLX and we want to use the same one.
|
||||
|
||||
if (is_library_loaded("libEGL.so.1", &libegl) ||
|
||||
is_library_loaded("libGLX.so.0", &libglx)) {
|
||||
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (libgl)
|
||||
return GL3W_OK;
|
||||
else
|
||||
close_libgl();
|
||||
}
|
||||
|
||||
if (is_library_loaded("libGL.so", &libgl))
|
||||
return GL3W_OK;
|
||||
if (is_library_loaded("libGL.so.1", &libgl))
|
||||
return GL3W_OK;
|
||||
if (is_library_loaded("libGL.so.3", &libgl))
|
||||
return GL3W_OK;
|
||||
|
||||
// Neither is already loaded, so we have to load one. Try EGL first
|
||||
// because it is supported under both X11 and Wayland.
|
||||
|
||||
// Load OpenGL + EGL
|
||||
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||
libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (libgl && libegl)
|
||||
return GL3W_OK;
|
||||
else
|
||||
close_libgl();
|
||||
|
||||
// Fall back to legacy libGL, which includes GLX
|
||||
// While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983
|
||||
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL);
|
||||
|
||||
if (libgl)
|
||||
return GL3W_OK;
|
||||
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
}
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
int res = open_libs();
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (libegl)
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
|
||||
else if (libglx)
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
|
||||
else
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
|
||||
|
||||
if (!gl_get_proc_address) {
|
||||
close_libgl();
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
}
|
||||
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static GL3WglProc get_proc(const char* proc)
|
||||
{
|
||||
GL3WglProc res = NULL;
|
||||
|
||||
// Before EGL version 1.5, eglGetProcAddress doesn't support querying core
|
||||
// functions and may return a dummy function if we try, so try to load the
|
||||
// function from the GL library directly first.
|
||||
if (libegl)
|
||||
*(void**)(&res) = dlsym(libgl, proc);
|
||||
|
||||
if (!res)
|
||||
res = gl_get_proc_address(proc);
|
||||
|
||||
if (!libegl && !res)
|
||||
*(void**)(&res) = dlsym(libgl, proc);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct { int major, minor; } version;
|
||||
|
||||
static int parse_version(void)
|
||||
{
|
||||
if (!glGetIntegerv)
|
||||
return GL3W_ERROR_INIT;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &version.major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &version.minor);
|
||||
if (version.major == 0 && version.minor == 0)
|
||||
{
|
||||
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||
if (const char* gl_version = (const char*)glGetString(GL_VERSION))
|
||||
sscanf(gl_version, "%d.%d", &version.major, &version.minor);
|
||||
}
|
||||
if (version.major < 2)
|
||||
return GL3W_ERROR_OPENGL_VERSION;
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc);
|
||||
|
||||
int imgl3wInit(void)
|
||||
{
|
||||
int res = open_libgl();
|
||||
if (res)
|
||||
return res;
|
||||
atexit(close_libgl);
|
||||
return imgl3wInit2(get_proc);
|
||||
}
|
||||
|
||||
int imgl3wInit2(GL3WGetProcAddressProc proc)
|
||||
{
|
||||
load_procs(proc);
|
||||
return parse_version();
|
||||
}
|
||||
|
||||
int imgl3wIsSupported(int major, int minor)
|
||||
{
|
||||
if (major < 2)
|
||||
return 0;
|
||||
if (version.major == major)
|
||||
return version.minor >= minor;
|
||||
return version.major >= major;
|
||||
}
|
||||
|
||||
GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }
|
||||
|
||||
static const char *proc_names[] = {
|
||||
"glActiveTexture",
|
||||
"glAttachShader",
|
||||
"glBindBuffer",
|
||||
"glBindSampler",
|
||||
"glBindTexture",
|
||||
"glBindVertexArray",
|
||||
"glBlendEquation",
|
||||
"glBlendEquationSeparate",
|
||||
"glBlendFuncSeparate",
|
||||
"glBufferData",
|
||||
"glBufferSubData",
|
||||
"glClear",
|
||||
"glClearColor",
|
||||
"glCompileShader",
|
||||
"glCreateProgram",
|
||||
"glCreateShader",
|
||||
"glDeleteBuffers",
|
||||
"glDeleteProgram",
|
||||
"glDeleteShader",
|
||||
"glDeleteTextures",
|
||||
"glDeleteVertexArrays",
|
||||
"glDetachShader",
|
||||
"glDisable",
|
||||
"glDisableVertexAttribArray",
|
||||
"glDrawElements",
|
||||
"glDrawElementsBaseVertex",
|
||||
"glEnable",
|
||||
"glEnableVertexAttribArray",
|
||||
"glFlush",
|
||||
"glGenBuffers",
|
||||
"glGenTextures",
|
||||
"glGenVertexArrays",
|
||||
"glGetAttribLocation",
|
||||
"glGetError",
|
||||
"glGetIntegerv",
|
||||
"glGetProgramInfoLog",
|
||||
"glGetProgramiv",
|
||||
"glGetShaderInfoLog",
|
||||
"glGetShaderiv",
|
||||
"glGetString",
|
||||
"glGetStringi",
|
||||
"glGetUniformLocation",
|
||||
"glGetVertexAttribPointerv",
|
||||
"glGetVertexAttribiv",
|
||||
"glIsEnabled",
|
||||
"glIsProgram",
|
||||
"glLinkProgram",
|
||||
"glPixelStorei",
|
||||
"glPolygonMode",
|
||||
"glReadPixels",
|
||||
"glScissor",
|
||||
"glShaderSource",
|
||||
"glTexImage2D",
|
||||
"glTexParameteri",
|
||||
"glUniform1i",
|
||||
"glUniformMatrix4fv",
|
||||
"glUseProgram",
|
||||
"glVertexAttribPointer",
|
||||
"glViewport",
|
||||
};
|
||||
|
||||
GL3W_API union ImGL3WProcs imgl3wProcs;
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = proc(proc_names[i]);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
54
physicaly-based-renderer/imgui-docking/imgui_impl_win32.h
Normal file
54
physicaly-based-renderer/imgui-docking/imgui_impl_win32.h
Normal file
@ -0,0 +1,54 @@
|
||||
// dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||
|
||||
// Win32 message handler your application need to call.
|
||||
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
|
||||
#if 0
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
// DPI-related helpers (optional)
|
||||
// - Use to enable DPI awareness without having to create an application manifest.
|
||||
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||
|
||||
// Transparency related helpers (optional) [experimental]
|
||||
// - Use to enable alpha compositing transparency with the desktop.
|
||||
// - Use together with e.g. clearing your framebuffer with zero-alpha.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
3941
physicaly-based-renderer/imgui-docking/imgui_internal.h
Normal file
3941
physicaly-based-renderer/imgui-docking/imgui_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
4525
physicaly-based-renderer/imgui-docking/imgui_tables.cpp
Normal file
4525
physicaly-based-renderer/imgui-docking/imgui_tables.cpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
physicaly-based-renderer/imgui-docking/imgui_tables.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui_tables.o
Normal file
Binary file not shown.
10577
physicaly-based-renderer/imgui-docking/imgui_widgets.cpp
Normal file
10577
physicaly-based-renderer/imgui-docking/imgui_widgets.cpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
physicaly-based-renderer/imgui-docking/imgui_widgets.o
Normal file
BIN
physicaly-based-renderer/imgui-docking/imgui_widgets.o
Normal file
Binary file not shown.
627
physicaly-based-renderer/imgui-docking/imstb_rectpack.h
Normal file
627
physicaly-based-renderer/imgui-docking/imstb_rectpack.h
Normal file
@ -0,0 +1,627 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
//
|
||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Before #including,
|
||||
//
|
||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||
//
|
||||
// in the file that you want to have the implementation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
//
|
||||
// Has only had a few tests run, may have issues.
|
||||
//
|
||||
// More docs to come.
|
||||
//
|
||||
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||
//
|
||||
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||
//
|
||||
// Please note: better rectangle packers are welcome! Please
|
||||
// implement them to the same API, but with a different init
|
||||
// function.
|
||||
//
|
||||
// Credits
|
||||
//
|
||||
// Library
|
||||
// Sean Barrett
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// github:IntellectualKitty
|
||||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||
// 0.01: initial release
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// See end of file for license information.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// INCLUDE SECTION
|
||||
//
|
||||
|
||||
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||
|
||||
#define STB_RECT_PACK_VERSION 1
|
||||
|
||||
#ifdef STBRP_STATIC
|
||||
#define STBRP_DEF static
|
||||
#else
|
||||
#define STBRP_DEF extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
typedef int stbrp_coord;
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||
// are 'num_rects' many of them.
|
||||
//
|
||||
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||
// have the 'was_packed' flag set to 0.
|
||||
//
|
||||
// You should not try to access the 'rects' array from another thread
|
||||
// while this function is running, as the function temporarily reorders
|
||||
// the array while it executes.
|
||||
//
|
||||
// To pack into another rectangle, you need to call stbrp_init_target
|
||||
// again. To continue packing into the same rectangle, you can call
|
||||
// this function again. Calling this multiple times with multiple rect
|
||||
// arrays will probably produce worse packing results than calling it
|
||||
// a single time with the full rectangle array, but the option is
|
||||
// available.
|
||||
//
|
||||
// The function returns 1 if all of the rectangles were successfully
|
||||
// packed and 0 otherwise.
|
||||
|
||||
struct stbrp_rect
|
||||
{
|
||||
// reserved for your use:
|
||||
int id;
|
||||
|
||||
// input:
|
||||
stbrp_coord w, h;
|
||||
|
||||
// output:
|
||||
stbrp_coord x, y;
|
||||
int was_packed; // non-zero if valid packing
|
||||
|
||||
}; // 16 bytes, nominally
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||
// Initialize a rectangle packer to:
|
||||
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||
//
|
||||
// You must call this function every time you start packing into a new target.
|
||||
//
|
||||
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||
// the call (or calls) finish.
|
||||
//
|
||||
// Note: to guarantee best results, either:
|
||||
// 1. make sure 'num_nodes' >= 'width'
|
||||
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||
//
|
||||
// If you don't do either of the above things, widths will be quantized to multiples
|
||||
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||
//
|
||||
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||
// may run out of temporary storage and be unable to pack some rectangles.
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||
// Optionally call this function after init but before doing any packing to
|
||||
// change the handling of the out-of-temp-memory scenario, described above.
|
||||
// If you call init again, this will be reset to the default (false).
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||
// Optionally select which packing heuristic the library should use. Different
|
||||
// heuristics will produce better/worse results for different data sets.
|
||||
// If you call init again, this will be reset to the default.
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP_HEURISTIC_Skyline_default=0,
|
||||
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// the details of the following structures don't matter to you, but they must
|
||||
// be visible so you can handle the memory allocations for them
|
||||
|
||||
struct stbrp_node
|
||||
{
|
||||
stbrp_coord x,y;
|
||||
stbrp_node *next;
|
||||
};
|
||||
|
||||
struct stbrp_context
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int align;
|
||||
int init_mode;
|
||||
int heuristic;
|
||||
int num_nodes;
|
||||
stbrp_node *active_head;
|
||||
stbrp_node *free_head;
|
||||
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPLEMENTATION SECTION
|
||||
//
|
||||
|
||||
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||
#ifndef STBRP_SORT
|
||||
#include <stdlib.h>
|
||||
#define STBRP_SORT qsort
|
||||
#endif
|
||||
|
||||
#ifndef STBRP_ASSERT
|
||||
#include <assert.h>
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#define STBRP__CDECL __cdecl
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#define STBRP__CDECL
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP__INIT_skyline = 1
|
||||
};
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||
{
|
||||
switch (context->init_mode) {
|
||||
case STBRP__INIT_skyline:
|
||||
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||
context->heuristic = heuristic;
|
||||
break;
|
||||
default:
|
||||
STBRP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||
{
|
||||
if (allow_out_of_mem)
|
||||
// if it's ok to run out of memory, then don't bother aligning them;
|
||||
// this gives better packing, but may fail due to OOM (even though
|
||||
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||
context->align = 1;
|
||||
else {
|
||||
// if it's not ok to run out of memory, then quantize the widths
|
||||
// so that num_nodes is always enough nodes.
|
||||
//
|
||||
// I.e. num_nodes * align >= width
|
||||
// align >= width / num_nodes
|
||||
// align = ceil(width/num_nodes)
|
||||
|
||||
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
nodes[i].next = NULL;
|
||||
context->init_mode = STBRP__INIT_skyline;
|
||||
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||
context->free_head = &nodes[0];
|
||||
context->active_head = &context->extra[0];
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
context->num_nodes = num_nodes;
|
||||
stbrp_setup_allow_out_of_mem(context, 0);
|
||||
|
||||
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||
context->extra[0].x = 0;
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
context->extra[1].y = (1<<30);
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
// find minimum y position if it starts at x1
|
||||
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||
{
|
||||
stbrp_node *node = first;
|
||||
int x1 = x0 + width;
|
||||
int min_y, visited_width, waste_area;
|
||||
|
||||
STBRP__NOTUSED(c);
|
||||
|
||||
STBRP_ASSERT(first->x <= x0);
|
||||
|
||||
#if 0
|
||||
// skip in case we're past the node
|
||||
while (node->next->x <= x0)
|
||||
++node;
|
||||
#else
|
||||
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||
#endif
|
||||
|
||||
STBRP_ASSERT(node->x <= x0);
|
||||
|
||||
min_y = 0;
|
||||
waste_area = 0;
|
||||
visited_width = 0;
|
||||
while (node->x < x1) {
|
||||
if (node->y > min_y) {
|
||||
// raise min_y higher.
|
||||
// we've accounted for all waste up to min_y,
|
||||
// but we'll now add more waste for everything we've visted
|
||||
waste_area += visited_width * (node->y - min_y);
|
||||
min_y = node->y;
|
||||
// the first time through, visited_width might be reduced
|
||||
if (node->x < x0)
|
||||
visited_width += node->next->x - x0;
|
||||
else
|
||||
visited_width += node->next->x - node->x;
|
||||
} else {
|
||||
// add waste area
|
||||
int under_width = node->next->x - node->x;
|
||||
if (under_width + visited_width > width)
|
||||
under_width = width - visited_width;
|
||||
waste_area += under_width * (min_y - node->y);
|
||||
visited_width += under_width;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
*pwaste = waste_area;
|
||||
return min_y;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x,y;
|
||||
stbrp_node **prev_link;
|
||||
} stbrp__findresult;
|
||||
|
||||
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||
{
|
||||
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||
stbrp__findresult fr;
|
||||
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||
|
||||
// align to multiple of c->align
|
||||
width = (width + c->align - 1);
|
||||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
// if it can't possibly fit, bail immediately
|
||||
if (width > c->width || height > c->height) {
|
||||
fr.prev_link = NULL;
|
||||
fr.x = fr.y = 0;
|
||||
return fr;
|
||||
}
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
int y,waste;
|
||||
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||
// bottom left
|
||||
if (y < best_y) {
|
||||
best_y = y;
|
||||
best = prev;
|
||||
}
|
||||
} else {
|
||||
// best-fit
|
||||
if (y + height <= c->height) {
|
||||
// can only use it if it first vertically
|
||||
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||
|
||||
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||
//
|
||||
// e.g, if fitting
|
||||
//
|
||||
// ____________________
|
||||
// |____________________|
|
||||
//
|
||||
// into
|
||||
//
|
||||
// | |
|
||||
// | ____________|
|
||||
// |____________|
|
||||
//
|
||||
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||
//
|
||||
// This makes BF take about 2x the time
|
||||
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||
tail = c->active_head;
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
// find first node that's admissible
|
||||
while (tail->x < width)
|
||||
tail = tail->next;
|
||||
while (tail) {
|
||||
int xpos = tail->x - width;
|
||||
int y,waste;
|
||||
STBRP_ASSERT(xpos >= 0);
|
||||
// find the left position that matches this
|
||||
while (node->next->x <= xpos) {
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||
if (y + height <= c->height) {
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
|
||||
fr.prev_link = best;
|
||||
fr.x = best_x;
|
||||
fr.y = best_y;
|
||||
return fr;
|
||||
}
|
||||
|
||||
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||
{
|
||||
// find best position according to heuristic
|
||||
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||
stbrp_node *node, *cur;
|
||||
|
||||
// bail if:
|
||||
// 1. it failed
|
||||
// 2. the best node doesn't fit (we don't always check this)
|
||||
// 3. we're out of memory
|
||||
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||
res.prev_link = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
// on success, create new node
|
||||
node = context->free_head;
|
||||
node->x = (stbrp_coord) res.x;
|
||||
node->y = (stbrp_coord) (res.y + height);
|
||||
|
||||
context->free_head = node->next;
|
||||
|
||||
// insert the new node into the right starting point, and
|
||||
// let 'cur' point to the remaining nodes needing to be
|
||||
// stiched back in
|
||||
|
||||
cur = *res.prev_link;
|
||||
if (cur->x < res.x) {
|
||||
// preserve the existing one, so start testing with the next one
|
||||
stbrp_node *next = cur->next;
|
||||
cur->next = node;
|
||||
cur = next;
|
||||
} else {
|
||||
*res.prev_link = node;
|
||||
}
|
||||
|
||||
// from here, traverse cur and free the nodes, until we get to one
|
||||
// that shouldn't be freed
|
||||
while (cur->next && cur->next->x <= res.x + width) {
|
||||
stbrp_node *next = cur->next;
|
||||
// move the current node to the free list
|
||||
cur->next = context->free_head;
|
||||
context->free_head = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
// stitch the list back in
|
||||
node->next = cur;
|
||||
|
||||
if (cur->x < res.x + width)
|
||||
cur->x = (stbrp_coord) (res.x + width);
|
||||
|
||||
#ifdef _DEBUG
|
||||
cur = context->active_head;
|
||||
while (cur->x < context->width) {
|
||||
STBRP_ASSERT(cur->x < cur->next->x);
|
||||
cur = cur->next;
|
||||
}
|
||||
STBRP_ASSERT(cur->next == NULL);
|
||||
|
||||
{
|
||||
int count=0;
|
||||
cur = context->active_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
cur = context->free_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
STBRP_ASSERT(count == context->num_nodes+2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->h > q->h)
|
||||
return -1;
|
||||
if (p->h < q->h)
|
||||
return 1;
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
|
||||
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = i;
|
||||
}
|
||||
|
||||
// sort according to heuristic
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||
} else {
|
||||
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||
if (fr.prev_link) {
|
||||
rects[i].x = (stbrp_coord) fr.x;
|
||||
rects[i].y = (stbrp_coord) fr.y;
|
||||
} else {
|
||||
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsort
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||
|
||||
// set was_packed flags and all_rects_packed status
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||
if (!rects[i].was_packed)
|
||||
all_rects_packed = 0;
|
||||
}
|
||||
|
||||
// return the all_rects_packed status
|
||||
return all_rects_packed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
1469
physicaly-based-renderer/imgui-docking/imstb_textedit.h
Normal file
1469
physicaly-based-renderer/imgui-docking/imstb_textedit.h
Normal file
File diff suppressed because it is too large
Load Diff
5085
physicaly-based-renderer/imgui-docking/imstb_truetype.h
Normal file
5085
physicaly-based-renderer/imgui-docking/imstb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
10
physicaly-based-renderer/imgui.ini
Normal file
10
physicaly-based-renderer/imgui.ini
Normal file
@ -0,0 +1,10 @@
|
||||
[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Scene Controls]
|
||||
Pos=121,151
|
||||
Size=334,445
|
||||
Collapsed=0
|
||||
|
7991
physicaly-based-renderer/include/stb_image.h
Normal file
7991
physicaly-based-renderer/include/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
802
physicaly-based-renderer/main.cpp
Normal file
802
physicaly-based-renderer/main.cpp
Normal file
@ -0,0 +1,802 @@
|
||||
// main.cpp
|
||||
// A minimal physically based renderer with ImGui integration,
|
||||
// normal mapping (with per-vertex tangents),
|
||||
// YAML-based material loading and material saving via yaml-cpp.
|
||||
// Uses OpenGL, GLFW, GLEW, GLM, ImGui (and IM_PI), stb_image, and yaml-cpp.
|
||||
// Compile (e.g. on Linux) with:
|
||||
// g++ main.cpp -lglfw -lGLEW -lGL -ldl -limgui -lyaml-cpp -o pbr_renderer
|
||||
// (Adjust include paths and linker flags as needed.)
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
// ImGui includes.
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h" // for IM_PI (ImGui's internal constant)
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
|
||||
// stb_image for texture loading.
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
// yaml-cpp for YAML material loading and saving.
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Shader sources
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// --- Vertex Shader ---
|
||||
// Now accepts a tangent attribute (location = 3) so we can compute a TBN matrix.
|
||||
const char* vertexShaderSource = R"(
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
layout (location = 2) in vec2 aTexCoords;
|
||||
layout (location = 3) in vec3 aTangent;
|
||||
|
||||
out vec3 WorldPos;
|
||||
out vec3 Normal;
|
||||
out vec2 TexCoords;
|
||||
out vec3 Tangent;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main(){
|
||||
WorldPos = vec3(model * vec4(aPos, 1.0));
|
||||
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||
// For tangent, we simply transform with the model matrix (ignoring potential scale issues).
|
||||
Tangent = mat3(model) * aTangent;
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = projection * view * vec4(WorldPos, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
// --- Fragment Shader ---
|
||||
// Uses a uniform for PI (set from ImGui's internal IM_PI) and supports texture maps.
|
||||
// It now also supports a normal map: if enabled, it uses TBN to compute a perturbed normal.
|
||||
const char* fragmentShaderSource = R"(
|
||||
#version 330 core
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec3 WorldPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoords;
|
||||
in vec3 Tangent;
|
||||
|
||||
uniform vec3 camPos;
|
||||
|
||||
// Base material parameters.
|
||||
uniform vec3 albedo;
|
||||
uniform float metallic;
|
||||
uniform float roughness;
|
||||
uniform float ao;
|
||||
|
||||
// Texture map usage flags and samplers.
|
||||
uniform bool useAlbedoMap;
|
||||
uniform bool useMetallicMap;
|
||||
uniform bool useRoughnessMap;
|
||||
uniform bool useAOMap;
|
||||
uniform bool useNormalMap;
|
||||
|
||||
uniform sampler2D albedoMap;
|
||||
uniform sampler2D metallicMap;
|
||||
uniform sampler2D roughnessMap;
|
||||
uniform sampler2D aoMap;
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// Use ImGui's internal PI constant.
|
||||
uniform float PI;
|
||||
|
||||
// Light parameters.
|
||||
uniform vec3 lightPos;
|
||||
uniform vec3 lightColor;
|
||||
|
||||
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
|
||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
float DistributionGGX(vec3 N, vec3 H, float roughness) {
|
||||
float a = roughness * roughness;
|
||||
float a2 = a * a;
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float NdotH2 = NdotH * NdotH;
|
||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||
denom = PI * denom * denom;
|
||||
return a2 / max(denom, 0.001);
|
||||
}
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float roughness) {
|
||||
float r = roughness + 1.0;
|
||||
float k = (r * r) / 8.0;
|
||||
return NdotV / (NdotV * (1.0 - k) + k);
|
||||
}
|
||||
|
||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx1 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx2 = GeometrySchlickGGX(NdotL, roughness);
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
void main(){
|
||||
// Start with the geometry normal.
|
||||
vec3 N = normalize(Normal);
|
||||
|
||||
// If a normal map is used, sample the normal map and compute a perturbed normal.
|
||||
if (useNormalMap) {
|
||||
vec3 tangentNormal = texture(normalMap, TexCoords).rgb;
|
||||
tangentNormal = tangentNormal * 2.0 - 1.0; // Remap from [0,1] to [-1,1]
|
||||
vec3 T = normalize(Tangent);
|
||||
vec3 B = normalize(cross(N, T));
|
||||
mat3 TBN = mat3(T, B, N);
|
||||
N = normalize(TBN * tangentNormal);
|
||||
}
|
||||
|
||||
vec3 V = normalize(camPos - WorldPos);
|
||||
|
||||
// Get material parameter values from textures (if enabled) or use fallback values.
|
||||
vec3 albedoValue = albedo;
|
||||
if (useAlbedoMap)
|
||||
albedoValue = texture(albedoMap, TexCoords).rgb;
|
||||
|
||||
float metallicValue = metallic;
|
||||
if (useMetallicMap)
|
||||
metallicValue = texture(metallicMap, TexCoords).r;
|
||||
|
||||
float roughnessValue = roughness;
|
||||
if (useRoughnessMap)
|
||||
roughnessValue = texture(roughnessMap, TexCoords).r;
|
||||
|
||||
float aoValue = ao;
|
||||
if (useAOMap)
|
||||
aoValue = texture(aoMap, TexCoords).r;
|
||||
|
||||
// Calculate reflectance at normal incidence.
|
||||
vec3 F0 = vec3(0.04);
|
||||
F0 = mix(F0, albedoValue, metallicValue);
|
||||
|
||||
vec3 L = normalize(lightPos - WorldPos);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float NDF = DistributionGGX(N, H, roughnessValue);
|
||||
float G = GeometrySmith(N, V, L, roughnessValue);
|
||||
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
|
||||
|
||||
vec3 numerator = NDF * G * F;
|
||||
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001;
|
||||
vec3 specular = numerator / denominator;
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = vec3(1.0) - kS;
|
||||
kD *= 1.0 - metallicValue;
|
||||
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
vec3 irradiance = lightColor * NdotL;
|
||||
vec3 diffuse = (albedoValue / PI);
|
||||
|
||||
vec3 color = (kD * diffuse + specular) * irradiance;
|
||||
vec3 ambient = vec3(0.03) * albedoValue * aoValue;
|
||||
color += ambient;
|
||||
|
||||
// Simple HDR tonemapping & gamma correction.
|
||||
color = color / (color + vec3(1.0));
|
||||
color = pow(color, vec3(1.0/2.2));
|
||||
|
||||
FragColor = vec4(color, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Helper functions: Shader compilation and linking.
|
||||
// --------------------------------------------------------------------------------------
|
||||
GLuint compileShader(GLenum shaderType, const char* source) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &source, nullptr);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success){
|
||||
char infoLog[512];
|
||||
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
|
||||
std::cerr << "Shader compilation failed:\n" << infoLog << std::endl;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint createProgram(GLuint vertexShader, GLuint fragmentShader) {
|
||||
GLuint program = glCreateProgram();
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
glLinkProgram(program);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||
if (!success){
|
||||
char infoLog[512];
|
||||
glGetProgramInfoLog(program, 512, nullptr, infoLog);
|
||||
std::cerr << "Program linking failed:\n" << infoLog << std::endl;
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Texture loading helper using stb_image.
|
||||
// --------------------------------------------------------------------------------------
|
||||
GLuint LoadTexture(const char* path) {
|
||||
int width, height, nrChannels;
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 0);
|
||||
if (!data) {
|
||||
std::cout << "Failed to load texture: " << path << std::endl;
|
||||
return 0;
|
||||
}
|
||||
GLenum format;
|
||||
if(nrChannels == 1)
|
||||
format = GL_RED;
|
||||
else if(nrChannels == 3)
|
||||
format = GL_RGB;
|
||||
else if(nrChannels == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
// Texture parameters.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Sphere mesh generation with tangents.
|
||||
// Produces per-vertex data: position (3), normal (3), texcoords (2), tangent (3) → 11 floats/vertex.
|
||||
// --------------------------------------------------------------------------------------
|
||||
void generateSphere(std::vector<float>& vertices, std::vector<unsigned int>& indices,
|
||||
unsigned int X_SEGMENTS = 64, unsigned int Y_SEGMENTS = 64) {
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
|
||||
for (unsigned int y = 0; y <= Y_SEGMENTS; ++y) {
|
||||
for (unsigned int x = 0; x <= X_SEGMENTS; ++x) {
|
||||
float xSegment = static_cast<float>(x) / X_SEGMENTS;
|
||||
float ySegment = static_cast<float>(y) / Y_SEGMENTS;
|
||||
// Using ImGui's IM_PI for consistency.
|
||||
float xPos = std::cos(xSegment * 2.0f * IM_PI) * std::sin(ySegment * IM_PI);
|
||||
float yPos = std::cos(ySegment * IM_PI);
|
||||
float zPos = std::sin(xSegment * 2.0f * IM_PI) * std::sin(ySegment * IM_PI);
|
||||
// Position.
|
||||
vertices.push_back(xPos);
|
||||
vertices.push_back(yPos);
|
||||
vertices.push_back(zPos);
|
||||
// Normal (unit sphere: same as position).
|
||||
vertices.push_back(xPos);
|
||||
vertices.push_back(yPos);
|
||||
vertices.push_back(zPos);
|
||||
// Texture coordinates.
|
||||
vertices.push_back(xSegment);
|
||||
vertices.push_back(ySegment);
|
||||
// Tangent: derivative with respect to u.
|
||||
float tangentX = -std::sin(xSegment * 2.0f * IM_PI);
|
||||
float tangentY = 0.0f;
|
||||
float tangentZ = std::cos(xSegment * 2.0f * IM_PI);
|
||||
vertices.push_back(tangentX);
|
||||
vertices.push_back(tangentY);
|
||||
vertices.push_back(tangentZ);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int y = 0; y < Y_SEGMENTS; ++y) {
|
||||
for (unsigned int x = 0; x < X_SEGMENTS; ++x) {
|
||||
unsigned int i0 = y * (X_SEGMENTS + 1) + x;
|
||||
unsigned int i1 = i0 + 1;
|
||||
unsigned int i2 = i0 + (X_SEGMENTS + 1);
|
||||
unsigned int i3 = i2 + 1;
|
||||
indices.push_back(i0);
|
||||
indices.push_back(i2);
|
||||
indices.push_back(i1);
|
||||
indices.push_back(i1);
|
||||
indices.push_back(i2);
|
||||
indices.push_back(i3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Material and Sphere Instance structures.
|
||||
// The Material now includes a normal map.
|
||||
// --------------------------------------------------------------------------------------
|
||||
struct Material {
|
||||
glm::vec3 albedo;
|
||||
float metallic;
|
||||
float roughness;
|
||||
float ao;
|
||||
|
||||
// Texture IDs.
|
||||
GLuint albedoTex;
|
||||
GLuint metallicTex;
|
||||
GLuint roughnessTex;
|
||||
GLuint aoTex;
|
||||
GLuint normalTex;
|
||||
|
||||
// Flags indicating if a texture map is used.
|
||||
bool useAlbedoMap;
|
||||
bool useMetallicMap;
|
||||
bool useRoughnessMap;
|
||||
bool useAOMap;
|
||||
bool useNormalMap;
|
||||
|
||||
// File path buffers for manual texture loading via ImGui.
|
||||
char albedoPath[256];
|
||||
char metallicPath[256];
|
||||
char roughnessPath[256];
|
||||
char aoPath[256];
|
||||
char normalPath[256];
|
||||
|
||||
Material() : albedo(0.5f, 0.0f, 0.0f), metallic(0.0f), roughness(0.5f), ao(1.0f),
|
||||
albedoTex(0), metallicTex(0), roughnessTex(0), aoTex(0), normalTex(0),
|
||||
useAlbedoMap(false), useMetallicMap(false), useRoughnessMap(false),
|
||||
useAOMap(false), useNormalMap(false)
|
||||
{
|
||||
strcpy(albedoPath, "");
|
||||
strcpy(metallicPath, "");
|
||||
strcpy(roughnessPath, "");
|
||||
strcpy(aoPath, "");
|
||||
strcpy(normalPath, "");
|
||||
}
|
||||
};
|
||||
|
||||
struct SphereInstance {
|
||||
glm::vec3 position;
|
||||
float rotation; // Rotation angle (in radians).
|
||||
Material material;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// YAML Material Loading
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Expects a YAML file with keys: albedo (list of 3), metallic, roughness, ao,
|
||||
// plus optional texture paths: albedo_texture, metallic_texture, roughness_texture, ao_texture, normal_texture.
|
||||
Material loadMaterialFromYAML(const std::string& filename) {
|
||||
Material mat;
|
||||
try {
|
||||
YAML::Node config = YAML::LoadFile(filename);
|
||||
if (config["albedo"]) {
|
||||
mat.albedo = glm::vec3(config["albedo"][0].as<float>(),
|
||||
config["albedo"][1].as<float>(),
|
||||
config["albedo"][2].as<float>());
|
||||
}
|
||||
if (config["metallic"])
|
||||
mat.metallic = config["metallic"].as<float>();
|
||||
if (config["roughness"])
|
||||
mat.roughness = config["roughness"].as<float>();
|
||||
if (config["ao"])
|
||||
mat.ao = config["ao"].as<float>();
|
||||
|
||||
if (config["albedo_texture"]) {
|
||||
std::string path = config["albedo_texture"].as<std::string>();
|
||||
strncpy(mat.albedoPath, path.c_str(), sizeof(mat.albedoPath));
|
||||
GLuint tex = LoadTexture(mat.albedoPath);
|
||||
if (tex != 0) {
|
||||
mat.albedoTex = tex;
|
||||
mat.useAlbedoMap = true;
|
||||
}
|
||||
}
|
||||
if (config["metallic_texture"]) {
|
||||
std::string path = config["metallic_texture"].as<std::string>();
|
||||
strncpy(mat.metallicPath, path.c_str(), sizeof(mat.metallicPath));
|
||||
GLuint tex = LoadTexture(mat.metallicPath);
|
||||
if (tex != 0) {
|
||||
mat.metallicTex = tex;
|
||||
mat.useMetallicMap = true;
|
||||
}
|
||||
}
|
||||
if (config["roughness_texture"]) {
|
||||
std::string path = config["roughness_texture"].as<std::string>();
|
||||
strncpy(mat.roughnessPath, path.c_str(), sizeof(mat.roughnessPath));
|
||||
GLuint tex = LoadTexture(mat.roughnessPath);
|
||||
if (tex != 0) {
|
||||
mat.roughnessTex = tex;
|
||||
mat.useRoughnessMap = true;
|
||||
}
|
||||
}
|
||||
if (config["ao_texture"]) {
|
||||
std::string path = config["ao_texture"].as<std::string>();
|
||||
strncpy(mat.aoPath, path.c_str(), sizeof(mat.aoPath));
|
||||
GLuint tex = LoadTexture(mat.aoPath);
|
||||
if (tex != 0) {
|
||||
mat.aoTex = tex;
|
||||
mat.useAOMap = true;
|
||||
}
|
||||
}
|
||||
if (config["normal_texture"]) {
|
||||
std::string path = config["normal_texture"].as<std::string>();
|
||||
strncpy(mat.normalPath, path.c_str(), sizeof(mat.normalPath));
|
||||
GLuint tex = LoadTexture(mat.normalPath);
|
||||
if (tex != 0) {
|
||||
mat.normalTex = tex;
|
||||
mat.useNormalMap = true;
|
||||
}
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
std::cerr << "Error loading YAML material from file " << filename << ": " << e.what() << std::endl;
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// YAML Material Saving
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Saves a material to a YAML file with keys similar to the loader.
|
||||
bool saveMaterialToYAML(const std::string& filename, const Material& mat) {
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "albedo" << YAML::Value << YAML::Flow << std::vector<float>{mat.albedo.r, mat.albedo.g, mat.albedo.b};
|
||||
out << YAML::Key << "metallic" << YAML::Value << mat.metallic;
|
||||
out << YAML::Key << "roughness" << YAML::Value << mat.roughness;
|
||||
out << YAML::Key << "ao" << YAML::Value << mat.ao;
|
||||
if (mat.useAlbedoMap)
|
||||
out << YAML::Key << "albedo_texture" << YAML::Value << std::string(mat.albedoPath);
|
||||
if (mat.useMetallicMap)
|
||||
out << YAML::Key << "metallic_texture" << YAML::Value << std::string(mat.metallicPath);
|
||||
if (mat.useRoughnessMap)
|
||||
out << YAML::Key << "roughness_texture" << YAML::Value << std::string(mat.roughnessPath);
|
||||
if (mat.useAOMap)
|
||||
out << YAML::Key << "ao_texture" << YAML::Value << std::string(mat.aoPath);
|
||||
if (mat.useNormalMap)
|
||||
out << YAML::Key << "normal_texture" << YAML::Value << std::string(mat.normalPath);
|
||||
out << YAML::EndMap;
|
||||
|
||||
std::ofstream fout(filename);
|
||||
if (!fout.is_open()){
|
||||
std::cerr << "Failed to open file for saving material: " << filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
fout << out.c_str();
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Main
|
||||
// --------------------------------------------------------------------------------------
|
||||
int main(){
|
||||
// Initialize GLFW.
|
||||
if (!glfwInit()){
|
||||
std::cerr << "Failed to initialize GLFW!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "PBR Renderer with ImGui, Normal Mapping & YAML Materials", nullptr, nullptr);
|
||||
if (!window){
|
||||
std::cerr << "Failed to create GLFW window!" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Initialize GLEW.
|
||||
glewExperimental = GL_TRUE;
|
||||
if (glewInit() != GLEW_OK){
|
||||
std::cerr << "Failed to initialize GLEW!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Setup ImGui context.
|
||||
// ----------------------------------------------------------------------------------
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Compile shaders and create shader program.
|
||||
// ----------------------------------------------------------------------------------
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
|
||||
GLuint shaderProgram = createProgram(vertexShader, fragmentShader);
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Generate the sphere mesh (with position, normal, texcoords, tangent).
|
||||
// ----------------------------------------------------------------------------------
|
||||
std::vector<float> sphereVertices;
|
||||
std::vector<unsigned int> sphereIndices;
|
||||
generateSphere(sphereVertices, sphereIndices, 64, 64);
|
||||
unsigned int indexCount = sphereIndices.size();
|
||||
|
||||
GLuint VAO, VBO, EBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &EBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), &sphereVertices[0], GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphereIndices.size() * sizeof(unsigned int), &sphereIndices[0], GL_STATIC_DRAW);
|
||||
|
||||
// Vertex attributes: 0 = position (3), 1 = normal (3), 2 = texcoords (2), 3 = tangent (3).
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)(8 * sizeof(float)));
|
||||
glEnableVertexAttribArray(3);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Prepare scene data: a list of spheres.
|
||||
// ----------------------------------------------------------------------------------
|
||||
std::vector<SphereInstance> spheres;
|
||||
// Add one default sphere.
|
||||
spheres.push_back({ glm::vec3(0.0f), 0.0f, Material() });
|
||||
|
||||
// Global scene/light parameters.
|
||||
glm::vec3 camPos(0.0f, 0.0f, 5.0f);
|
||||
glm::vec3 lightPos(0.0f, 0.0f, 10.0f);
|
||||
glm::vec3 lightColor(300.0f, 300.0f, 300.0f);
|
||||
|
||||
// For YAML material loading via ImGui.
|
||||
static char yamlPathBuffer[256] = "";
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Main render loop.
|
||||
// ----------------------------------------------------------------------------------
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwPollEvents();
|
||||
|
||||
// Start new ImGui frame.
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// ImGui: Global Scene Controls.
|
||||
// ----------------------------------------------------------------------------------
|
||||
{
|
||||
ImGui::Begin("Scene Controls");
|
||||
|
||||
// Global light controls.
|
||||
ImGui::Text("Light Controls");
|
||||
ImGui::DragFloat3("Light Position", glm::value_ptr(lightPos), 0.1f);
|
||||
ImGui::ColorEdit3("Light Color", glm::value_ptr(lightColor));
|
||||
ImGui::Separator();
|
||||
|
||||
// Button to add a new sphere.
|
||||
if (ImGui::Button("Add Sphere")) {
|
||||
spheres.push_back({ glm::vec3(0.0f), 0.0f, Material() });
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
// Global YAML material loader: set file path and add a sphere from YAML.
|
||||
ImGui::InputText("YAML Material Path", yamlPathBuffer, sizeof(yamlPathBuffer));
|
||||
if (ImGui::Button("Add Sphere from YAML Material")) {
|
||||
Material matFromYAML = loadMaterialFromYAML(yamlPathBuffer);
|
||||
spheres.push_back({ glm::vec3(0.0f), 0.0f, matFromYAML });
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
// Per-sphere controls.
|
||||
for (size_t i = 0; i < spheres.size(); i++) {
|
||||
std::string header = "Sphere " + std::to_string(i);
|
||||
if (ImGui::CollapsingHeader(header.c_str())) {
|
||||
// Transform controls.
|
||||
ImGui::DragFloat3(("Position##" + std::to_string(i)).c_str(), glm::value_ptr(spheres[i].position), 0.1f);
|
||||
ImGui::DragFloat(("Rotation (radians)##" + std::to_string(i)).c_str(), &spheres[i].rotation, 0.01f);
|
||||
|
||||
// Material properties.
|
||||
ImGui::ColorEdit3(("Albedo##" + std::to_string(i)).c_str(), glm::value_ptr(spheres[i].material.albedo));
|
||||
ImGui::SliderFloat(("Metallic##" + std::to_string(i)).c_str(), &spheres[i].material.metallic, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat(("Roughness##" + std::to_string(i)).c_str(), &spheres[i].material.roughness, 0.05f, 1.0f);
|
||||
ImGui::SliderFloat(("AO##" + std::to_string(i)).c_str(), &spheres[i].material.ao, 0.0f, 1.0f);
|
||||
|
||||
// Texture map controls.
|
||||
ImGui::InputText(("Albedo Texture Path##" + std::to_string(i)).c_str(),
|
||||
spheres[i].material.albedoPath, sizeof(spheres[i].material.albedoPath));
|
||||
if (ImGui::Button(("Load Albedo Texture##" + std::to_string(i)).c_str())) {
|
||||
GLuint tex = LoadTexture(spheres[i].material.albedoPath);
|
||||
if (tex != 0) {
|
||||
spheres[i].material.albedoTex = tex;
|
||||
spheres[i].material.useAlbedoMap = true;
|
||||
}
|
||||
}
|
||||
ImGui::InputText(("Metallic Texture Path##" + std::to_string(i)).c_str(),
|
||||
spheres[i].material.metallicPath, sizeof(spheres[i].material.metallicPath));
|
||||
if (ImGui::Button(("Load Metallic Texture##" + std::to_string(i)).c_str())) {
|
||||
GLuint tex = LoadTexture(spheres[i].material.metallicPath);
|
||||
if (tex != 0) {
|
||||
spheres[i].material.metallicTex = tex;
|
||||
spheres[i].material.useMetallicMap = true;
|
||||
}
|
||||
}
|
||||
ImGui::InputText(("Roughness Texture Path##" + std::to_string(i)).c_str(),
|
||||
spheres[i].material.roughnessPath, sizeof(spheres[i].material.roughnessPath));
|
||||
if (ImGui::Button(("Load Roughness Texture##" + std::to_string(i)).c_str())) {
|
||||
GLuint tex = LoadTexture(spheres[i].material.roughnessPath);
|
||||
if (tex != 0) {
|
||||
spheres[i].material.roughnessTex = tex;
|
||||
spheres[i].material.useRoughnessMap = true;
|
||||
}
|
||||
}
|
||||
ImGui::InputText(("AO Texture Path##" + std::to_string(i)).c_str(),
|
||||
spheres[i].material.aoPath, sizeof(spheres[i].material.aoPath));
|
||||
if (ImGui::Button(("Load AO Texture##" + std::to_string(i)).c_str())) {
|
||||
GLuint tex = LoadTexture(spheres[i].material.aoPath);
|
||||
if (tex != 0) {
|
||||
spheres[i].material.aoTex = tex;
|
||||
spheres[i].material.useAOMap = true;
|
||||
}
|
||||
}
|
||||
ImGui::InputText(("Normal Texture Path##" + std::to_string(i)).c_str(),
|
||||
spheres[i].material.normalPath, sizeof(spheres[i].material.normalPath));
|
||||
if (ImGui::Button(("Load Normal Texture##" + std::to_string(i)).c_str())) {
|
||||
GLuint tex = LoadTexture(spheres[i].material.normalPath);
|
||||
if (tex != 0) {
|
||||
spheres[i].material.normalTex = tex;
|
||||
spheres[i].material.useNormalMap = true;
|
||||
}
|
||||
}
|
||||
|
||||
// YAML material reloading.
|
||||
static char sphereYAMLPath[256] = "";
|
||||
ImGui::InputText(("YAML Material Path##" + std::to_string(i)).c_str(), sphereYAMLPath, sizeof(sphereYAMLPath));
|
||||
if (ImGui::Button(("Load Material from YAML##" + std::to_string(i)).c_str())) {
|
||||
Material newMat = loadMaterialFromYAML(sphereYAMLPath);
|
||||
spheres[i].material = newMat;
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Material Saving UI.
|
||||
// ---------------------------
|
||||
// We use a simple static buffer per sphere to specify a save file path.
|
||||
static char saveYAMLPath[256] = "";
|
||||
ImGui::InputText(("Save YAML Path##" + std::to_string(i)).c_str(), saveYAMLPath, sizeof(saveYAMLPath));
|
||||
if (ImGui::Button(("Save Material to YAML##" + std::to_string(i)).c_str())) {
|
||||
if (saveMaterialToYAML(std::string(saveYAMLPath), spheres[i].material)) {
|
||||
std::cout << "Saved material for sphere " << i << " to " << saveYAMLPath << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Button(("Remove Sphere##" + std::to_string(i)).c_str())) {
|
||||
spheres.erase(spheres.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Rendering.
|
||||
// ----------------------------------------------------------------------------------
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
float aspect = width / static_cast<float>(height);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Setup camera matrices.
|
||||
glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 100.0f);
|
||||
glm::mat4 view = glm::lookAt(camPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0));
|
||||
|
||||
glUseProgram(shaderProgram);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniform3fv(glGetUniformLocation(shaderProgram, "camPos"), 1, glm::value_ptr(camPos));
|
||||
// Set light uniforms.
|
||||
glUniform3fv(glGetUniformLocation(shaderProgram, "lightPos"), 1, glm::value_ptr(lightPos));
|
||||
glUniform3fv(glGetUniformLocation(shaderProgram, "lightColor"), 1, glm::value_ptr(lightColor));
|
||||
// Pass ImGui's internal PI constant.
|
||||
glUniform1f(glGetUniformLocation(shaderProgram, "PI"), IM_PI);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
for (const auto& sphere : spheres) {
|
||||
// Compute model matrix.
|
||||
glm::mat4 model = glm::translate(glm::mat4(1.0f), sphere.position);
|
||||
model = glm::rotate(model, sphere.rotation, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
|
||||
// Set fallback material uniforms.
|
||||
glUniform3fv(glGetUniformLocation(shaderProgram, "albedo"), 1, glm::value_ptr(sphere.material.albedo));
|
||||
glUniform1f(glGetUniformLocation(shaderProgram, "metallic"), sphere.material.metallic);
|
||||
glUniform1f(glGetUniformLocation(shaderProgram, "roughness"), sphere.material.roughness);
|
||||
glUniform1f(glGetUniformLocation(shaderProgram, "ao"), sphere.material.ao);
|
||||
|
||||
// Set texture usage flags.
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "useAlbedoMap"), sphere.material.useAlbedoMap ? 1 : 0);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "useMetallicMap"), sphere.material.useMetallicMap ? 1 : 0);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "useRoughnessMap"), sphere.material.useRoughnessMap ? 1 : 0);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "useAOMap"), sphere.material.useAOMap ? 1 : 0);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "useNormalMap"), sphere.material.useNormalMap ? 1 : 0);
|
||||
|
||||
// Bind textures if enabled.
|
||||
if (sphere.material.useAlbedoMap) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, sphere.material.albedoTex);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "albedoMap"), 0);
|
||||
}
|
||||
if (sphere.material.useMetallicMap) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, sphere.material.metallicTex);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "metallicMap"), 1);
|
||||
}
|
||||
if (sphere.material.useRoughnessMap) {
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, sphere.material.roughnessTex);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "roughnessMap"), 2);
|
||||
}
|
||||
if (sphere.material.useAOMap) {
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, sphere.material.aoTex);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "aoMap"), 3);
|
||||
}
|
||||
if (sphere.material.useNormalMap) {
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
glBindTexture(GL_TEXTURE_2D, sphere.material.normalTex);
|
||||
glUniform1i(glGetUniformLocation(shaderProgram, "normalMap"), 4);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Render ImGui over the scene.
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Cleanup.
|
||||
// ----------------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &EBO);
|
||||
glDeleteProgram(shaderProgram);
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
BIN
physicaly-based-renderer/main.exe
Normal file
BIN
physicaly-based-renderer/main.exe
Normal file
Binary file not shown.
BIN
physicaly-based-renderer/main.o
Normal file
BIN
physicaly-based-renderer/main.o
Normal file
Binary file not shown.
9
physicaly-based-renderer/metal.mat
Normal file
9
physicaly-based-renderer/metal.mat
Normal file
@ -0,0 +1,9 @@
|
||||
albedo: [1, 1, 1]
|
||||
metallic: 0
|
||||
roughness: 0.0500000007
|
||||
ao: 0
|
||||
albedo_texture: C:\Users\spenc\Downloads\used-stainless-steel-bl\used-stainless-steel-bl\used-stainless-steel_albedo.png
|
||||
metallic_texture: C:\Users\spenc\Downloads\used-stainless-steel-bl\used-stainless-steel-bl\used-stainless-steel_metallic.png
|
||||
roughness_texture: C:\Users\spenc\Downloads\used-stainless-steel-bl\used-stainless-steel-bl\used-stainless-steel_roughness.png
|
||||
ao_texture: C:\Users\spenc\Downloads\used-stainless-steel-bl\used-stainless-steel-bl\used-stainless-steel_ao.png
|
||||
normal_texture: C:\Users\spenc\Downloads\used-stainless-steel-bl\used-stainless-steel-bl\used-stainless-steel_normal-ogl.png
|
371
physics/main.py
Normal file
371
physics/main.py
Normal file
@ -0,0 +1,371 @@
|
||||
import pygame
|
||||
import sys
|
||||
import random
|
||||
import math
|
||||
from pygame.math import Vector2
|
||||
|
||||
# -------------------------------
|
||||
# Component System and Base Classes
|
||||
# -------------------------------
|
||||
|
||||
class Component:
|
||||
def __init__(self, owner):
|
||||
self.owner = owner
|
||||
def update(self, dt):
|
||||
pass
|
||||
|
||||
# RigidBody provides linear and angular motion
|
||||
class RigidBody(Component):
|
||||
def __init__(self, owner, mass=1.0):
|
||||
super().__init__(owner)
|
||||
self.mass = mass
|
||||
self.inv_mass = 1.0 / mass if mass != 0 else 0
|
||||
self.velocity = Vector2(0, 0)
|
||||
self.force = Vector2(0, 0)
|
||||
self.angle = 0.0 # in radians
|
||||
self.angular_velocity = 0.0
|
||||
self.torque = 0.0
|
||||
self.inertia = 1.0 # moment of inertia (set later)
|
||||
self.inv_inertia = 1.0
|
||||
def update(self, dt):
|
||||
# --- Linear integration ---
|
||||
acceleration = self.force * self.inv_mass
|
||||
self.velocity += acceleration * dt
|
||||
self.owner.pos += self.velocity * dt
|
||||
self.force = Vector2(0, 0)
|
||||
# --- Angular integration ---
|
||||
angular_acc = self.torque * self.inv_inertia
|
||||
self.angular_velocity += angular_acc * dt
|
||||
self.angle += self.angular_velocity * dt
|
||||
self.torque = 0.0
|
||||
def apply_force(self, force, point=None):
|
||||
self.force += force
|
||||
if point is not None:
|
||||
# Torque = r x force (scalar in 2D: r.x * force.y - r.y * force.x)
|
||||
r = point - self.owner.pos
|
||||
self.torque += r.cross(force)
|
||||
|
||||
# -------------------------------
|
||||
# Collision Components
|
||||
# -------------------------------
|
||||
|
||||
# Base CollisionComponent (extends Component)
|
||||
class CollisionComponent(Component):
|
||||
def __init__(self, owner):
|
||||
super().__init__(owner)
|
||||
# A draw method is provided for debugging outlines.
|
||||
def draw(self, surface):
|
||||
pass
|
||||
|
||||
# CircleCollider extends CollisionComponent
|
||||
class CircleCollider(CollisionComponent):
|
||||
def __init__(self, owner, radius):
|
||||
super().__init__(owner)
|
||||
self.radius = radius
|
||||
def get_position(self):
|
||||
return self.owner.pos
|
||||
def draw(self, surface):
|
||||
pygame.draw.circle(surface, (255,255,255),
|
||||
(int(self.owner.pos.x), int(self.owner.pos.y)),
|
||||
self.radius, 1)
|
||||
|
||||
# SquareCollider extends CollisionComponent
|
||||
class SquareCollider(CollisionComponent):
|
||||
def __init__(self, owner, width, height):
|
||||
super().__init__(owner)
|
||||
self.width = width
|
||||
self.height = height
|
||||
def get_corners(self):
|
||||
hw = self.width / 2
|
||||
hh = self.height / 2
|
||||
# Retrieve the current rotation (in radians) from the RigidBody if present.
|
||||
rb = self.owner.get_component(RigidBody)
|
||||
angle = rb.angle if rb else 0
|
||||
# Define corners in local space.
|
||||
corners = [Vector2(-hw, -hh), Vector2(hw, -hh),
|
||||
Vector2(hw, hh), Vector2(-hw, hh)]
|
||||
# Pygame’s rotate() expects degrees.
|
||||
rotated = [corner.rotate(math.degrees(angle)) + self.owner.pos for corner in corners]
|
||||
return rotated
|
||||
def draw(self, surface):
|
||||
corners = self.get_corners()
|
||||
points = [(p.x, p.y) for p in corners]
|
||||
pygame.draw.polygon(surface, (255,255,255), points, 1)
|
||||
|
||||
# PolygonCollider extends CollisionComponent
|
||||
class PolygonCollider(CollisionComponent):
|
||||
def __init__(self, owner, points):
|
||||
super().__init__(owner)
|
||||
# points is a list of Vector2 objects, defined in local space.
|
||||
self.points = points
|
||||
def get_transformed_points(self):
|
||||
rb = self.owner.get_component(RigidBody)
|
||||
angle = rb.angle if rb else 0
|
||||
transformed = [p.rotate(math.degrees(angle)) + self.owner.pos for p in self.points]
|
||||
return transformed
|
||||
def draw(self, surface):
|
||||
points = self.get_transformed_points()
|
||||
pts = [(p.x, p.y) for p in points]
|
||||
pygame.draw.polygon(surface, (255,255,255), pts, 1)
|
||||
|
||||
# -------------------------------
|
||||
# GameObject: Entities in the Scene
|
||||
# -------------------------------
|
||||
|
||||
class GameObject:
|
||||
def __init__(self, pos):
|
||||
self.pos = Vector2(pos)
|
||||
self.components = []
|
||||
def add_component(self, comp):
|
||||
self.components.append(comp)
|
||||
def get_component(self, comp_type):
|
||||
for comp in self.components:
|
||||
if isinstance(comp, comp_type):
|
||||
return comp
|
||||
return None
|
||||
def update(self, dt):
|
||||
for comp in self.components:
|
||||
comp.update(dt)
|
||||
|
||||
|
||||
def draw(self, surface):
|
||||
# Draw any collision shapes (for visualization)
|
||||
for comp in self.components:
|
||||
if isinstance(comp, CollisionComponent):
|
||||
comp.draw(surface)
|
||||
|
||||
# -------------------------------
|
||||
# Collision Detection Functions
|
||||
# -------------------------------
|
||||
|
||||
def circle_vs_circle(circleA, circleB):
|
||||
posA = circleA.get_position()
|
||||
posB = circleB.get_position()
|
||||
rA = circleA.radius
|
||||
rB = circleB.radius
|
||||
diff = posB - posA
|
||||
dist = diff.length()
|
||||
if dist < (rA + rB):
|
||||
penetration = (rA + rB) - dist
|
||||
normal = diff.normalize() if dist != 0 else Vector2(1, 0)
|
||||
return normal, penetration
|
||||
return None, None
|
||||
|
||||
def circle_vs_square(circle, square):
|
||||
center = circle.get_position()
|
||||
# Obtain the square’s rotation angle (in radians)
|
||||
rb = square.owner.get_component(RigidBody)
|
||||
angle = rb.angle if rb else 0
|
||||
# Transform the circle center into the square's local space.
|
||||
local_center = (center - square.owner.pos).rotate(-math.degrees(angle))
|
||||
hw = square.width / 2
|
||||
hh = square.height / 2
|
||||
closest_x = max(-hw, min(local_center.x, hw))
|
||||
closest_y = max(-hh, min(local_center.y, hh))
|
||||
closest = Vector2(closest_x, closest_y)
|
||||
diff = local_center - closest
|
||||
dist = diff.length()
|
||||
if dist < circle.radius:
|
||||
penetration = circle.radius - dist
|
||||
local_normal = diff.normalize() if dist != 0 else Vector2(1, 0)
|
||||
# Rotate the normal back to world space.
|
||||
normal = local_normal.rotate(math.degrees(angle))
|
||||
return normal, penetration
|
||||
return None, None
|
||||
|
||||
def square_vs_square(sq1, sq2):
|
||||
corners1 = sq1.get_corners()
|
||||
corners2 = sq2.get_corners()
|
||||
axes = []
|
||||
def get_axes(corners):
|
||||
axes = []
|
||||
for i in range(len(corners)):
|
||||
edge = corners[(i+1) % len(corners)] - corners[i]
|
||||
if edge.length() == 0:
|
||||
continue
|
||||
normal = Vector2(-edge.y, edge.x).normalize()
|
||||
axes.append(normal)
|
||||
return axes
|
||||
axes.extend(get_axes(corners1))
|
||||
axes.extend(get_axes(corners2))
|
||||
min_overlap = float('inf')
|
||||
collision_normal = None
|
||||
for axis in axes:
|
||||
proj1 = [p.dot(axis) for p in corners1]
|
||||
proj2 = [p.dot(axis) for p in corners2]
|
||||
min1, max1 = min(proj1), max(proj1)
|
||||
min2, max2 = min(proj2), max(proj2)
|
||||
if max1 < min2 or max2 < min1:
|
||||
return None, None # Separating axis found; no collision.
|
||||
overlap = min(max1, max2) - max(min1, min2)
|
||||
if overlap < min_overlap:
|
||||
min_overlap = overlap
|
||||
collision_normal = axis
|
||||
# Ensure the normal points from sq1 to sq2.
|
||||
if (sq2.owner.pos - sq1.owner.pos).dot(collision_normal) < 0:
|
||||
collision_normal = -collision_normal
|
||||
return collision_normal, min_overlap
|
||||
|
||||
# Universal collision check selects routine based on collider types.
|
||||
def check_collision(objA, objB):
|
||||
colA = objA.get_component(CollisionComponent)
|
||||
colB = objB.get_component(CollisionComponent)
|
||||
if colA is None or colB is None:
|
||||
return None, None
|
||||
# Circle vs Circle.
|
||||
if isinstance(colA, CircleCollider) and isinstance(colB, CircleCollider):
|
||||
return circle_vs_circle(colA, colB)
|
||||
# Circle vs Square.
|
||||
if isinstance(colA, CircleCollider) and isinstance(colB, SquareCollider):
|
||||
return circle_vs_square(colA, colB)
|
||||
if isinstance(colA, SquareCollider) and isinstance(colB, CircleCollider):
|
||||
normal, penetration = circle_vs_square(colB, colA)
|
||||
if normal is not None:
|
||||
return -normal, penetration
|
||||
# Square vs Square.
|
||||
if isinstance(colA, SquareCollider) and isinstance(colB, SquareCollider):
|
||||
return square_vs_square(colA, colB)
|
||||
# (PolygonCollider collisions can be implemented similarly using SAT.)
|
||||
return None, None
|
||||
|
||||
# -------------------------------
|
||||
# Collision Resolution
|
||||
# -------------------------------
|
||||
|
||||
def resolve_collision(objA, objB, normal, penetration):
|
||||
rbA = objA.get_component(RigidBody)
|
||||
rbB = objB.get_component(RigidBody)
|
||||
if rbA is None or rbB is None:
|
||||
return
|
||||
total_inv_mass = rbA.inv_mass + rbB.inv_mass
|
||||
if total_inv_mass == 0:
|
||||
return
|
||||
# Correct positions (simple penetration resolution).
|
||||
correction = normal * (penetration / total_inv_mass * 0.5)
|
||||
objA.pos -= correction * rbA.inv_mass
|
||||
objB.pos += correction * rbB.inv_mass
|
||||
|
||||
# Relative velocity along collision normal.
|
||||
relative_vel = rbB.velocity - rbA.velocity
|
||||
vel_along_normal = relative_vel.dot(normal)
|
||||
if vel_along_normal > 0:
|
||||
return # They are separating.
|
||||
restitution = 0.5 # Bounce factor.
|
||||
impulse_scalar = -(1 + restitution) * vel_along_normal / total_inv_mass
|
||||
impulse = normal * impulse_scalar
|
||||
|
||||
rbA.velocity -= impulse * rbA.inv_mass
|
||||
rbB.velocity += impulse * rbB.inv_mass
|
||||
|
||||
# --- Angular response ---
|
||||
# As an approximation, we use the average of the object centers as the contact point.
|
||||
contact_point = (objA.pos + objB.pos) * 0.5
|
||||
rA = contact_point - objA.pos
|
||||
rB = contact_point - objB.pos
|
||||
# In 2D, the scalar "cross" is computed with Vector2.cross().
|
||||
rbA.torque -= rA.cross(impulse)
|
||||
rbB.torque += rB.cross(impulse)
|
||||
|
||||
# -------------------------------
|
||||
# Utility: Set the Moment of Inertia Based on the Collider Type
|
||||
# -------------------------------
|
||||
|
||||
def set_inertia(obj):
|
||||
rb = obj.get_component(RigidBody)
|
||||
if rb is None:
|
||||
return
|
||||
col = obj.get_component(CollisionComponent)
|
||||
if isinstance(col, CircleCollider):
|
||||
rb.inertia = 0.5 * rb.mass * (col.radius ** 2)
|
||||
elif isinstance(col, SquareCollider):
|
||||
rb.inertia = rb.mass * ((col.width ** 2 + col.height ** 2) / 12)
|
||||
else:
|
||||
rb.inertia = rb.mass # Default value.
|
||||
rb.inv_inertia = 1.0 / rb.inertia if rb.inertia != 0 else 0
|
||||
|
||||
# -------------------------------
|
||||
# Object Factories
|
||||
# -------------------------------
|
||||
|
||||
def create_circle(pos, radius, mass):
|
||||
obj = GameObject(pos)
|
||||
rb = RigidBody(obj, mass)
|
||||
obj.add_component(rb)
|
||||
col = CircleCollider(obj, radius)
|
||||
obj.add_component(col)
|
||||
set_inertia(obj)
|
||||
return obj
|
||||
|
||||
def create_square(pos, width, height, mass):
|
||||
obj = GameObject(pos)
|
||||
rb = RigidBody(obj, mass)
|
||||
obj.add_component(rb)
|
||||
col = SquareCollider(obj, width, height)
|
||||
obj.add_component(col)
|
||||
set_inertia(obj)
|
||||
return obj
|
||||
|
||||
# -------------------------------
|
||||
# Main Game Loop and Setup
|
||||
# -------------------------------
|
||||
|
||||
pygame.init()
|
||||
WIDTH, HEIGHT = 800, 600
|
||||
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||
pygame.display.set_caption("Physics Engine with Rotating Collisions")
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
# Create a list of objects.
|
||||
objects = []
|
||||
|
||||
# Create some circles.
|
||||
for _ in range(3):
|
||||
pos = (random.randint(100, 700), random.randint(100, 300))
|
||||
circle = create_circle(pos, random.randint(15, 30), mass=1)
|
||||
# Give each circle an initial random velocity.
|
||||
circle.get_component(RigidBody).velocity = Vector2(random.uniform(-100, 100), random.uniform(-100, 100))
|
||||
objects.append(circle)
|
||||
|
||||
# Create some squares ("cubes").
|
||||
for _ in range(3):
|
||||
pos = (random.randint(100, 700), random.randint(100, 300))
|
||||
square = create_square(pos, random.randint(30, 50), random.randint(30, 50), mass=2)
|
||||
square.get_component(RigidBody).velocity = Vector2(random.uniform(-100, 100), random.uniform(-100, 100))
|
||||
objects.append(square)
|
||||
|
||||
# Gravity (pixels per second^2).
|
||||
GRAVITY = Vector2(0, 200)
|
||||
|
||||
# Main loop.
|
||||
running = True
|
||||
while running:
|
||||
dt = clock.tick(60) / 1000.0 # Delta time in seconds.
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
# Apply gravity to each object.
|
||||
for obj in objects:
|
||||
rb = obj.get_component(RigidBody)
|
||||
if rb:
|
||||
rb.apply_force(GRAVITY * rb.mass)
|
||||
|
||||
# Update all objects.
|
||||
for obj in objects:
|
||||
obj.update(dt)
|
||||
|
||||
# Check collisions between all pairs.
|
||||
for i in range(len(objects)):
|
||||
for j in range(i + 1, len(objects)):
|
||||
normal, penetration = check_collision(objects[i], objects[j])
|
||||
if normal is not None:
|
||||
resolve_collision(objects[i], objects[j], normal, penetration)
|
||||
|
||||
# Rendering.
|
||||
screen.fill((30, 30, 30))
|
||||
for obj in objects:
|
||||
obj.draw(screen)
|
||||
pygame.display.flip()
|
||||
|
||||
pygame.quit()
|
||||
sys.exit()
|
Loading…
Reference in New Issue
Block a user