collada: render materials/textures

This commit is contained in:
Zack Buhman 2026-03-16 22:48:54 -05:00
parent 829cea09ba
commit 5e24166ac8
16 changed files with 475 additions and 453 deletions

View File

@ -36,6 +36,7 @@ OBJS = \
src/line_art.o \
src/boids.o \
src/boids_scene.o \
src/dds_validate.o \
src/collada/scene.o \
src/collada/effect.o \
src/collada/node_state.o \

View File

@ -1,427 +0,0 @@
#include "collada/types.h"
namespace ship20 {
using namespace collada::types;
light const light_environmentambientlight = {
.type = light_type::AMBIENT,
.color = { 0.0f, 0.0f, 0.0f },
};
light const light_omni002_light = {
.type = light_type::POINT,
.color = { 1.0f, 1.0f, 1.0f },
};
light const light_omni003_light = {
.type = light_type::POINT,
.color = { 1.0f, 1.0f, 1.0f },
};
// shipple2_png
image const image_shipple2_png = {
.resource_name = "_0_SHIPPLE2_PNG",
};
image const * const images[] = {
&image_shipple2_png,
};
effect const effect_diffusetexture = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.588f, 0.588f, 0.588f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.5f, 0.5f, 0.5f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
effect const effect_cyanengine = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.9647059f, 1.0f, 1.0f},
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
effect const effect_emissivetexture = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.588f, 0.588f, 0.588f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
material const material_diffusetexture_material = {
.effect = &effect_diffusetexture,
};
material const material_cyanengine_material = {
.effect = &effect_cyanengine,
};
material const material_emissivetexture_material = {
.effect = &effect_emissivetexture,
};
input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = {
{
.semantic = "POSITION",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
{
.semantic = "NORMAL",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
{
.semantic = "TEXCOORD",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
};
triangles const triangles_geom_ship[] = {
{
.count = 2949, // triangles
.index_offset = 0, // indices
.inputs_index = 0, // index into inputs_list
},
{
.count = 60, // triangles
.index_offset = 8847, // indices
.inputs_index = 0, // index into inputs_list
},
{
.count = 239, // triangles
.index_offset = 9027, // indices
.inputs_index = 0, // index into inputs_list
},
};
geometry const geometry_geom_ship = {
.mesh = {
.triangles = triangles_geom_ship,
.triangles_count = 3,
.vertex_buffer_offset = 0,
.vertex_buffer_size = 133272,
.index_buffer_offset = 0,
.index_buffer_size = 38976,
}
};
geometry const * const geometries[] = {
&geometry_geom_ship,
};
transform const transforms_node_environmentambientlight[] = {
};
instance_geometry const instance_geometries_node_environmentambientlight[] = {
};
instance_controller const instance_controllers_node_environmentambientlight[] = {
};
instance_light const instance_lights_node_environmentambientlight[] = {
{
.light = &light_environmentambientlight,
}
};
channel const * const node_channels_node_environmentambientlight[] = {};
node const node_node_environmentambientlight = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_environmentambientlight,
.transforms_count = 0,
.instance_geometries = instance_geometries_node_environmentambientlight,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_environmentambientlight,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_environmentambientlight,
.instance_lights_count = 1,
.channels = node_channels_node_environmentambientlight,
.channels_count = 0,
};
transform const transforms_node_ship[] = {
{
.type = transform_type::ROTATE,
.rotate = {0.0f, 0.0f, 1.0f, -180.0f},
},
};
instance_material const instance_geometry_instance_materials_node_ship_0[] = {
{
.element_index = 1, // an index into mesh.triangles
.material = &material_cyanengine_material,
.emission = { .input_set = -1 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = -1 },
.specular = { .input_set = -1 },
},
{
.element_index = 0, // an index into mesh.triangles
.material = &material_diffusetexture_material,
.emission = { .input_set = -1 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = 0 },
.specular = { .input_set = -1 },
},
{
.element_index = 2, // an index into mesh.triangles
.material = &material_emissivetexture_material,
.emission = { .input_set = 0 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = 0 },
.specular = { .input_set = -1 },
},
};
instance_geometry const instance_geometries_node_ship[] = {
{
.geometry = &geometry_geom_ship,
.instance_materials = instance_geometry_instance_materials_node_ship_0,
.instance_materials_count = 3,
},
};
instance_controller const instance_controllers_node_ship[] = {
};
instance_light const instance_lights_node_ship[] = {
};
channel const * const node_channels_node_ship[] = {
};
node const node_node_ship = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_ship,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_ship,
.instance_geometries_count = 1,
.instance_controllers = instance_controllers_node_ship,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_ship,
.instance_lights_count = 0,
.channels = node_channels_node_ship,
.channels_count = 0,
};
transform const transforms_node_omni002[] = {
{
.type = transform_type::TRANSLATE,
.translate = {-286.5521f, 395.7583f, 161.5579f},
},
};
instance_geometry const instance_geometries_node_omni002[] = {
};
instance_controller const instance_controllers_node_omni002[] = {
};
instance_light const instance_lights_node_omni002[] = {
{
.light = &light_omni002_light,
}
};
channel const * const node_channels_node_omni002[] = {
};
node const node_node_omni002 = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_omni002,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_omni002,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_omni002,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_omni002,
.instance_lights_count = 1,
.channels = node_channels_node_omni002,
.channels_count = 0,
};
transform const transforms_node_omni003[] = {
{
.type = transform_type::TRANSLATE,
.translate = {333.2103f, -314.4593f, 161.5578f},
},
};
instance_geometry const instance_geometries_node_omni003[] = {
};
instance_controller const instance_controllers_node_omni003[] = {
};
instance_light const instance_lights_node_omni003[] = {
{
.light = &light_omni003_light,
}
};
channel const * const node_channels_node_omni003[] = {
};
node const node_node_omni003 = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_omni003,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_omni003,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_omni003,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_omni003,
.instance_lights_count = 1,
.channels = node_channels_node_omni003,
.channels_count = 0,
};
node const * const nodes[] = {
&node_node_environmentambientlight, // 0
&node_node_ship, // 1
&node_node_omni002, // 2
&node_node_omni003, // 3
};
inputs const inputs_list[] = {
{
.elements = input_elements_position_0_3_normal_0_3_texcoord_0_3,
.elements_count = 3,
},
};
types::descriptor const descriptor = {
.nodes = nodes,
.nodes_count = (sizeof (nodes)) / (sizeof (nodes[0])),
.inputs_list = inputs_list,
.inputs_list_count = (sizeof (inputs_list)) / (sizeof (inputs_list[0])),
.images = images,
.images_count = (sizeof (images)) / (sizeof (images[0])),
.position_normal_texture_buffer = "RES_SCENES_SHIP20_VTX",
.joint_weight_buffer = "RES_SCENES_SHIP20_VJW",
.index_buffer = "RES_SCENES_SHIP20_IDX",
};
}

View File

@ -23,7 +23,7 @@ light const light_omni003_light = {
// shipple2_png
image const image_shipple2_png = {
.resource_name = "_0_SHIPPLE2_PNG",
.resource_name = "data/scenes/ship20/shipple2.dds",
};
image const * const images[] = {

Binary file not shown.

View File

@ -18,9 +18,17 @@ namespace collada::scene {
static_skinned * vertex_arrays;
int * vertex_buffer_strides;
unsigned int * textures;
void load_layouts();
void load_images();
void load_scene(types::descriptor const * const descriptor);
void set_color_or_texture(types::color_or_texture const& color_or_texture,
unsigned int color_uniform,
unsigned int texture_unit);
void set_instance_material(types::instance_material const& instance_material);
void draw_geometry(types::geometry const & geometry,
types::instance_material const * const instance_materials,
int const instance_materials_count);

127
include/dds.h Normal file
View File

@ -0,0 +1,127 @@
//--------------------------------------------------------------------------------------
// dds.h
//
// This header defines constants and structures that are useful when parsing
// DDS files. DDS files were originally designed to use several structures
// and constants that are native to DirectDraw and are defined in ddraw.h,
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
// (compatible) constants and structures so that one can use DDS files
// without needing to include ddraw.h.
//--------------------------------------------------------------------------------------
#ifndef _DDS_H_
#define _DDS_H_
#pragma pack(push,1)
#define DDS_MAGIC 0x20534444 // "DDS "
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \
((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24 ))
struct DDS_PIXELFORMAT
{
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwFourCC;
unsigned int dwRGBBitCount;
unsigned int dwRBitMask;
unsigned int dwGBitMask;
unsigned int dwBBitMask;
unsigned int dwABitMask;
};
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
#define DDS_RGB 0x00000040 // DDPF_RGB
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
const DDS_PIXELFORMAT DDSPF_DXT1 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT2 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT3 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT4 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT5 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
const DDS_PIXELFORMAT DDSPF_R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
const DDS_PIXELFORMAT DDSPF_R5G6B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)
const DDS_PIXELFORMAT DDSPF_DX10 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };
#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
typedef struct
{
unsigned int dwSize;
unsigned int dwHeaderFlags;
unsigned int dwHeight;
unsigned int dwWidth;
unsigned int dwPitchOrLinearSize;
unsigned int dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwHeaderFlags
unsigned int dwMipMapCount;
unsigned int dwReserved1[11];
DDS_PIXELFORMAT ddspf;
unsigned int dwSurfaceFlags;
unsigned int dwCubemapFlags;
unsigned int dwReserved2[3];
} DDS_HEADER;
/*
typedef struct
{
DXGI_FORMAT dxgiFormat;
D3D10_RESOURCE_DIMENSION resourceDimension;
unsigned int miscFlag;
unsigned int arraySize;
unsigned int reserved;
} DDS_HEADER_DXT10;
*/
#pragma pack(pop)
#endif // _DDS_H

10
include/dds_validate.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "dds.h"
struct DDS_FILE {
unsigned int dwMagic;
DDS_HEADER header;
};
DDS_FILE const * dds_validate(void * data, unsigned int size, void ** out_data, int * out_size);

View File

@ -1,11 +1,11 @@
/**
* Loader generated by glad 2.0.8 on Thu Mar 5 16:16:42 2026
* Loader generated by glad 2.0.8 on Tue Mar 17 02:15:55 2026
*
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
*
* Generator: C/C++
* Specification: gl
* Extensions: 0
* Extensions: 1
*
* APIs:
* - gl:core=4.3
@ -19,10 +19,10 @@
* - ON_DEMAND = False
*
* Commandline:
* --api='gl:core=4.3' --extensions='' c
* --api='gl:core=4.3' --extensions='GL_EXT_texture_compression_s3tc' c
*
* Online:
* http://glad.sh/#api=gl%3Acore%3D4.3&extensions=&generator=c&options=
* http://glad.sh/#api=gl%3Acore%3D4.3&extensions=GL_EXT_texture_compression_s3tc&generator=c&options=
*
*/
@ -332,8 +332,12 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_COMPRESSED_RGBA 0x84EE
#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RG_RGTC2 0x8DBD
#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
@ -1578,6 +1582,8 @@ GLAD_API_CALL int GLAD_GL_VERSION_4_1;
GLAD_API_CALL int GLAD_GL_VERSION_4_2;
#define GL_VERSION_4_3 1
GLAD_API_CALL int GLAD_GL_VERSION_4_3;
#define GL_EXT_texture_compression_s3tc 1
GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc;
typedef void (GLAD_API_PTR *PFNGLACTIVESHADERPROGRAMPROC)(GLuint pipeline, GLuint program);

View File

@ -10,6 +10,8 @@ extern "C" {
unsigned int load_uniform_buffer(char const * const path);
void load_dds_texture_2D(char const * const path);
#ifdef __cplusplus
}
#endif

View File

@ -1,8 +1,65 @@
#version 430 core
out vec4 Color;
in vec3 PixelNormal;
in vec2 PixelTexture;
/*
in vec4 PixelViewPosition;
in vec4 PixelWorldPosition;
in vec4 PixelLightPosition;
*/
layout (location = 10) uniform vec4 EmissionColor;
layout (location = 11) uniform vec4 AmbientColor;
layout (location = 12) uniform vec4 DiffuseColor;
layout (location = 13) uniform vec4 SpecularColor;
layout (location = 14) uniform float shininess;
layout (location = 15) uniform sampler2D EmissionSampler;
layout (location = 16) uniform sampler2D AmbientSampler;
layout (location = 17) uniform sampler2D DiffuseSampler;
layout (location = 18) uniform sampler2D SpecularSampler;
layout (location = 19) uniform ivec4 TextureChannel;
layout (location = 0) out vec4 g_color;
//layout (location = 1) out vec4 g_position;
//layout (location = 2) out vec4 g_normal;
void main()
{
Color = vec4(1, 0, 0, 1);
vec4 emission;
vec4 ambient;
vec4 diffuse;
vec4 specular;
if (TextureChannel.x >= 0) { // emission
emission = texture(EmissionSampler, PixelTexture.xy);
} else {
emission = EmissionColor;
}
if (TextureChannel.y >= 0) { // ambient
ambient = texture(AmbientSampler, PixelTexture.xy);
} else {
ambient = AmbientColor;
}
if (TextureChannel.z >= 0) { // diffuse
diffuse = texture(DiffuseSampler, PixelTexture.xy);
} else {
diffuse = DiffuseColor;
}
if (TextureChannel.w >= 0) { // specular
specular = texture(SpecularSampler, PixelTexture.xy);
} else {
specular = SpecularColor;
}
vec3 color = emission.xyz * 0;
color += ambient.xyz * 0.05;
color += diffuse.xyz * 1;
color += specular.xyz * 0 * 0.3;
g_color = vec4(color, 1.0);
//g_color = vec4(PixelNormal.xyz, 1.0);
//g_color = vec4(PixelTexture.xy, 0, 1);
}

View File

@ -2,11 +2,17 @@
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec3 Texture;
layout (location = 2) in vec2 Texture;
layout (location = 0) uniform mat4 Transform;
out vec3 PixelNormal;
out vec2 PixelTexture;
void main()
{
PixelNormal = Normal;
PixelTexture = vec2(Texture.x, 1.0 - Texture.y);
gl_Position = Transform * vec4(Position, 1);
}

View File

@ -8,6 +8,7 @@
#include "new.h"
#include "file.h"
#include "view.h"
#include "opengl.h"
#include "collada/types.h"
#include "collada/instance_types.h"
@ -25,8 +26,29 @@ namespace collada::scene {
unsigned int blend_weight;
} attribute;
struct {
// vertex
unsigned int transform;
// fragment
unsigned int emission_color;
unsigned int ambient_color;
unsigned int diffuse_color;
unsigned int specular_color;
unsigned int shininess;
unsigned int emission_sampler;
unsigned int ambient_sampler;
unsigned int diffuse_sampler;
unsigned int specular_sampler;
unsigned int texture_channels;
} uniform;
struct {
unsigned int emission;
unsigned int ambient;
unsigned int diffuse;
unsigned int specular;
} texture_unit;
};
const layout layout = {
@ -38,7 +60,28 @@ namespace collada::scene {
.blend_weight = 4,
},
.uniform = {
// vertex
.transform = 0,
// fragment
.emission_color = 10,
.ambient_color = 11,
.diffuse_color = 12,
.specular_color = 13,
.shininess = 14,
.emission_sampler = 15,
.ambient_sampler = 16,
.diffuse_sampler = 17,
.specular_sampler = 18,
.texture_channels = 19,
},
.texture_unit {
.emission = GL_TEXTURE0,
.ambient = GL_TEXTURE1,
.diffuse = GL_TEXTURE2,
.specular = GL_TEXTURE3,
},
};
@ -197,6 +240,27 @@ namespace collada::scene {
return index_buffer;
}
void state::load_images()
{
textures = New<unsigned int>(descriptor->images_count);
glGenTextures(descriptor->images_count, textures);
for (int i = 0; i < descriptor->images_count; i++) {
types::image const * const image = descriptor->images[i];
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
load_dds_texture_2D(image->resource_name);
}
glBindTexture(GL_TEXTURE_2D, 0);
}
void state::load_scene(types::descriptor const * const descriptor)
{
this->descriptor = descriptor;
@ -206,6 +270,64 @@ namespace collada::scene {
vertex_buffer_pnt = load_vertex_buffer(descriptor->position_normal_texture_buffer);
vertex_buffer_jw = load_vertex_buffer(descriptor->joint_weight_buffer);
index_buffer = load_index_buffer(descriptor->index_buffer);
load_images();
}
void state::set_color_or_texture(types::color_or_texture const& color_or_texture,
unsigned int color_uniform,
unsigned int texture_unit)
{
switch (color_or_texture.type) {
case types::color_or_texture_type::COLOR:
glUniform4fv(color_uniform, 1, (float *)&color_or_texture.color);
break;
case types::color_or_texture_type::TEXTURE:
glActiveTexture(texture_unit);
glBindTexture(GL_TEXTURE_2D, textures[color_or_texture.texture.image_index]);
break;
default:
assert(false);
}
}
void state::set_instance_material(types::instance_material const& instance_material)
{
types::effect const& effect = *instance_material.material->effect;
switch (effect.type) {
case types::effect_type::BLINN:
set_color_or_texture(effect.blinn.emission, layout.uniform.emission_color, layout.texture_unit.emission);
set_color_or_texture(effect.blinn.ambient, layout.uniform.ambient_color, layout.texture_unit.ambient);
set_color_or_texture(effect.blinn.diffuse, layout.uniform.diffuse_color, layout.texture_unit.diffuse);
set_color_or_texture(effect.blinn.specular, layout.uniform.specular_color, layout.texture_unit.specular);
glUniform1f(layout.uniform.shininess, effect.blinn.shininess);
break;
case types::effect_type::LAMBERT:
set_color_or_texture(effect.lambert.emission, layout.uniform.emission_color, layout.texture_unit.emission);
set_color_or_texture(effect.lambert.ambient, layout.uniform.ambient_color, layout.texture_unit.ambient);
set_color_or_texture(effect.lambert.diffuse, layout.uniform.diffuse_color, layout.texture_unit.diffuse);
break;
case types::effect_type::PHONG:
set_color_or_texture(effect.phong.emission, layout.uniform.emission_color, layout.texture_unit.emission);
set_color_or_texture(effect.phong.ambient, layout.uniform.ambient_color, layout.texture_unit.ambient);
set_color_or_texture(effect.phong.diffuse, layout.uniform.diffuse_color, layout.texture_unit.diffuse);
set_color_or_texture(effect.phong.specular, layout.uniform.specular_color, layout.texture_unit.specular);
glUniform1f(layout.uniform.shininess, effect.phong.shininess);
break;
case types::effect_type::CONSTANT:
glUniform4fv(layout.uniform.emission_color, 1, (float *)&effect.constant.color);
break;
default:
break;
}
int texture_channels[4] = {
instance_material.emission.input_set,
instance_material.ambient.input_set,
instance_material.diffuse.input_set,
instance_material.specular.input_set,
};
glUniform4iv(layout.uniform.texture_channels, 1, texture_channels);
}
void state::draw_geometry(types::geometry const & geometry,
@ -217,10 +339,13 @@ namespace collada::scene {
types::mesh const& mesh = geometry.mesh;
for (int j = 0; j < instance_materials_count; j++) {
//if (j != 1)
//continue;
types::instance_material const& instance_material = instance_materials[j];
types::triangles const& triangles = mesh.triangles[instance_material.element_index];
//set_instance_material(instance_material);
set_instance_material(instance_material);
unsigned int vertex_buffer_offset = mesh.vertex_buffer_offset;
unsigned int vertex_buffer_stride = vertex_buffer_strides[triangles.inputs_index];
@ -235,7 +360,7 @@ namespace collada::scene {
unsigned int instance_count = 1;
unsigned int base_vertex = 0;
unsigned int base_instance = 1;
unsigned int base_instance = 0;
glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES,
index_count,
GL_UNSIGNED_INT,
@ -266,6 +391,16 @@ namespace collada::scene {
{
glUseProgram(collada::effect::program_static);
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&view::state.float_transform);
glUniform1i(layout.uniform.emission_sampler, 0);
glUniform1i(layout.uniform.ambient_sampler, 1);
glUniform1i(layout.uniform.diffuse_sampler, 2);
glUniform1i(layout.uniform.specular_sampler, 3);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GREATER);
glDisable(GL_CULL_FACE);
//glCullFace(GL_FRONT);
//glFrontFace(GL_CCW);
for (int i = 0; i < descriptor->nodes_count; i++) {
types::node const & node = *descriptor->nodes[i];

69
src/dds_validate.cpp Normal file
View File

@ -0,0 +1,69 @@
#include <assert.h>
#include <stdint.h>
#include "dds_validate.h"
static inline unsigned int max(unsigned int a, unsigned int b)
{
return (a > b) ? a : b;
}
struct dds_size_levels {
unsigned int const size;
unsigned int const levels;
};
static inline unsigned int dim(unsigned int d)
{
return max(1, (d / 4));
}
static inline dds_size_levels dds_mip_total_size(uintptr_t data,
unsigned int height,
unsigned int width,
unsigned int max_mip_levels)
{
unsigned int mip_total_size = 0;
unsigned int mip_levels = 0;
while (true) {
unsigned int mip_size = dim(height) * dim(width) * 8;
mip_total_size += mip_size;
//subresourceData[mip_levels].pSysMem = (const void *)data;
//subresourceData[mip_levels].SysMemPitch = dim(width) * 8;
mip_levels += 1;
assert(mip_levels <= max_mip_levels);
data += mip_size;
if (max_mip_levels == 1 || (width == 1 && height == 1))
break;
height /= 2;
width /= 2;
}
return (dds_size_levels){mip_total_size, mip_levels};
}
DDS_FILE const * dds_validate(void * data, unsigned int size, void ** out_data, int * out_size)
{
DDS_FILE const * const dds = (DDS_FILE const *)data;
assert(dds->dwMagic == DDS_MAGIC);
assert(dds->header.dwSize == 124);
assert(dds->header.ddspf.dwSize == 32);
assert(dds->header.ddspf.dwFlags == DDS_FOURCC);
assert(dds->header.ddspf.dwFourCC == MAKEFOURCC('D','X','T','1'));
assert(dds->header.dwDepth == 0);
uintptr_t image_data = ((uintptr_t)dds) + (sizeof (DDS_FILE));
dds_size_levels ret = dds_mip_total_size(image_data,
dds->header.dwHeight,
dds->header.dwWidth,
dds->header.dwMipMapCount);
assert(ret.size + (sizeof (DDS_FILE)) == size);
assert(ret.levels == dds->header.dwMipMapCount);
*out_data = (void *)image_data;
*out_size = ret.size;
return dds;
}

View File

@ -39,6 +39,7 @@ int GLAD_GL_VERSION_4_0 = 0;
int GLAD_GL_VERSION_4_1 = 0;
int GLAD_GL_VERSION_4_2 = 0;
int GLAD_GL_VERSION_4_3 = 0;
int GLAD_GL_EXT_texture_compression_s3tc = 0;
@ -1259,7 +1260,7 @@ static int glad_gl_find_extensions_gl(void) {
char **exts_i = NULL;
if (!glad_gl_get_extensions(&exts, &exts_i)) return 0;
GLAD_UNUSED(&glad_gl_has_extension);
GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_compression_s3tc");
glad_gl_free_extensions(exts_i);

View File

@ -7,12 +7,13 @@
#include "glad/gl.h"
#include "opengl.h"
#include "file.h"
#include "dds_validate.h"
unsigned int compile(const char * vertex_source,
unsigned int compile(char const * vertex_source,
int vertex_source_size,
const char * geometry_source,
char const * geometry_source,
int geometry_source_size,
const char * fragment_source,
char const * fragment_source,
int fragment_source_size)
{
int compile_status;
@ -75,16 +76,16 @@ unsigned int compile(const char * vertex_source,
return shader_program;
}
unsigned int compile_from_files(const char * vertex_path,
const char * geometry_path,
const char * fragment_path)
unsigned int compile_from_files(char const * vertex_path,
char const * geometry_path,
char const * fragment_path)
{
int vertex_source_size = 0;
char * vertex_source = NULL;
void * vertex_source = NULL;
int geometry_source_size = 0;
char * geometry_source = NULL;
void * geometry_source = NULL;
int fragment_source_size = 0;
char * fragment_source = NULL;
void * fragment_source = NULL;
vertex_source = read_file(vertex_path, &vertex_source_size);
assert(vertex_source != NULL);
@ -97,9 +98,9 @@ unsigned int compile_from_files(const char * vertex_path,
fragment_source = read_file(fragment_path, &fragment_source_size);
assert(fragment_source != NULL);
unsigned int program = compile(vertex_source, vertex_source_size,
geometry_source, geometry_source_size,
fragment_source, fragment_source_size);
unsigned int program = compile((char const *)vertex_source, vertex_source_size,
(char const *)geometry_source, geometry_source_size,
(char const *)fragment_source, fragment_source_size);
free(vertex_source);
free(geometry_source);
@ -125,3 +126,27 @@ unsigned int load_uniform_buffer(char const * const path)
return buffer;
}
void load_dds_texture_2D(char const * const path)
{
fprintf(stderr, "load DDS texture: %s\n", path);
int size;
void * data = read_file(path, &size);
assert(data != NULL);
void * image_data;
int image_size;
DDS_FILE const * dds = dds_validate(data, size, &image_data, &image_size);
glCompressedTexImage2D(GL_TEXTURE_2D,
0,
GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
dds->header.dwWidth,
dds->header.dwHeight,
0,
image_size,
image_data);
free(data);
}

View File

@ -380,6 +380,7 @@ void update_joystick(int joystick_index,
delta_yaw, delta_pitch);
view::apply_fov(0.01 * up + -0.01 * down);
/*
XMVECTOR sphere_position = view::state.at;
float sphere_radius = 0.48;
@ -411,7 +412,9 @@ void update_joystick(int joystick_index,
// apply the last direction impulse
view::state.at = sphere.center + direction;
}
*/
view::state.at = view::state.at + direction;
view::state.eye = view::state.at - view::state.direction * view::at_distance;
/*
@ -558,10 +561,9 @@ void update_mouse(int x, int y)
void draw()
{
if (false) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(-1.0f);
if (false) {
// possibly re-initialize geometry buffer if window width/height changes
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);