Skip to content

Commit

Permalink
texture
Browse files Browse the repository at this point in the history
  • Loading branch information
ousttrue committed Sep 23, 2024
1 parent 0bcdb6e commit abb658a
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 10 deletions.
7 changes: 7 additions & 0 deletions deps/sokol_samples/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ pub fn build(b: *std.Build) void {
sample_framework.root_module.addImport("sokol", sokol_dep.module("sokol"));
sample_framework.root_module.addImport("zigltf", zigltf_dep.module("zigltf"));
sample_framework.root_module.addImport("rowmath", rowmath_dep.module("rowmath"));
if (!target.result.isWasm()) {
const stb_dep = b.dependency("stb", .{});
sample_framework.addIncludePath(stb_dep.path(""));
sample_framework.addCSourceFile(.{
.file = b.path("sample_framework/stb/stb.c"),
});
}

// create a build step which invokes the Emscripten linker
var emsdk_dep_: ?*std.Build.Dependency = null;
Expand Down
4 changes: 4 additions & 0 deletions deps/sokol_samples/build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
.url = "git+https://github.com/ousttrue/gltf-test-models.git#55328b2d063141993373ab8c770c72d7cfda260f",
.hash = "1220aa78e130eb4c584dc21b408dcd26e8cfd30043e0f673ba6d229a0bfff592c54e",
},
.stb = .{
.url = "git+https://github.com/nothings/stb.git#f75e8d1cad7d90d72ef7a4661f1b994ef78b4e31",
.hash = "1220c4fe5a4c4ebec402f5cdef08bc264b56fb07f259107d2b01ba8d416d88624b50",
},
},
.paths = .{
"",
Expand Down
86 changes: 86 additions & 0 deletions deps/sokol_samples/sample_framework/Mesh.zig
Original file line number Diff line number Diff line change
@@ -1,15 +1,100 @@
const sokol = @import("sokol");
const sg = sokol.gfx;
const shader = @import("gltf.glsl.zig");
const stb = @import("stb/stb.zig");

pub const Vertex = struct {
position: [3]f32,
normal: [3]f32,
uv: [2]f32,
};

pub const Image = struct {
width: u32,
height: u32,
channels: u32,
pixels: []const u8,

pub const white = Image{
.width = 2,
.height = 2,
.channels = 4,
.pixels = &.{
255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
},
};

pub fn init(data: []const u8) ?@This() {
var img_width: c_int = undefined;
var img_height: c_int = undefined;
var num_channels: c_int = undefined;
const desired_channels = 4;
const pixels = stb.image.stbi_load_from_memory(
@ptrCast(&data[0]),
@intCast(data.len),
&img_width,
&img_height,
&num_channels,
desired_channels,
) orelse {
return null;
};
return .{
.width = @intCast(img_width),
.height = @intCast(img_height),
.channels = @intCast(num_channels),
.pixels = pixels[0..@intCast(img_width * img_height * num_channels)],
};
}

pub fn deinit(self: @This()) void {
stb.image.stbi_image_free(&self.pixels[0]);
}

pub fn byteLength(self: @This()) u32 {
return self.width * self.height * 4;
}
};

pub const Texture = struct {
fs: sg.StageBindings = sg.StageBindings{},

pub fn init(image: Image) @This() {
// init sokol
var texture = Texture{};
texture.fs.images[shader.SLOT_colorTexture2D] = sg.allocImage();
texture.fs.samplers[shader.SLOT_colorTextureSmp] = sg.allocSampler();
sg.initSampler(texture.fs.samplers[shader.SLOT_colorTextureSmp], .{
.wrap_u = .REPEAT,
.wrap_v = .REPEAT,
.min_filter = .LINEAR,
.mag_filter = .LINEAR,
.compare = .NEVER,
});

// initialize the sokol-gfx texture
var img_desc = sg.ImageDesc{
.width = @intCast(image.width),
.height = @intCast(image.height),
// set pixel_format to RGBA8 for WebGL
.pixel_format = .RGBA8,
};
img_desc.data.subimage[0][0] = .{
.ptr = &image.pixels[0],
.size = image.byteLength(),
};
sg.initImage(texture.fs.images[shader.SLOT_colorTexture2D], img_desc);

return texture;
}
};
pub const Submesh = struct {
submesh_params: shader.SubmeshParams,
draw_count: u32,
color_texture: Texture,
};

pub const Mesh = @This();
Expand Down Expand Up @@ -37,6 +122,7 @@ pub fn init(
.label = "gltf-indices",
});
}

return mesh;
}

Expand Down
42 changes: 38 additions & 4 deletions deps/sokol_samples/sample_framework/Scene.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ allocator: std.mem.Allocator = undefined,
meshes: []Mesh = &.{},
pip: sg.Pipeline = undefined,
gltf: ?std.json.Parsed(zigltf.Gltf) = null,
white_texture: Mesh.Texture = undefined,

pub fn init(self: *@This(), allocator: std.mem.Allocator) void {
self.allocator = allocator;
Expand All @@ -37,7 +38,10 @@ pub fn init(self: *@This(), allocator: std.mem.Allocator) void {
// pip_desc.layout.buffers[0].stride = 28;
pip_desc.layout.attrs[shader.ATTR_vs_aPos].format = .FLOAT3;
pip_desc.layout.attrs[shader.ATTR_vs_aNormal].format = .FLOAT3;
pip_desc.layout.attrs[shader.ATTR_vs_aTexCoord].format = .FLOAT2;
self.pip = sg.makePipeline(pip_desc);

self.white_texture = Mesh.Texture.init(Mesh.Image.white);
}

pub fn deinit(self: *@This()) void {
Expand Down Expand Up @@ -106,6 +110,16 @@ pub fn load(
mesh_vertices.items[vertex_count + i].normal = normal;
}
}
if (primitive.attributes.TEXCOORD_0) |tex0_accessor_index| {
// uv
const tex0s = try gltf_buffer.getAccessorBytes(
[2]f32,
tex0_accessor_index,
);
for (tex0s, 0..) |tex0, i| {
mesh_vertices.items[vertex_count + i].uv = tex0;
}
}

if (primitive.indices) |indices_accessor_index| {
// indies
Expand All @@ -129,11 +143,27 @@ pub fn load(
color = base_color;
}
}

var color_texture = self.white_texture;
if (material.pbrMetallicRoughness) |pbr| {
if (pbr.baseColorTexture) |base| {
const texture = gltf.textures[base.index];
if (texture.source) |source| {
const image_bytes = try gltf_buffer.getImageBytes(source);
if (Mesh.Image.init(image_bytes)) |image| {
defer image.deinit();
color_texture = Mesh.Texture.init(image);
}
}
}
}

try submeshes.append(.{
.draw_count = index_accessor.count,
.submesh_params = .{
.material_rgba = color,
},
.color_texture = color_texture,
});
} else {
@panic("no material");
Expand Down Expand Up @@ -218,7 +248,7 @@ fn draw_node(
}
}

fn draw_mesh(self: *const @This(), mesh_index: u32, vp: Mat4, model: Mat4) void {
fn draw_mesh(self: *@This(), mesh_index: u32, vp: Mat4, model: Mat4) void {
const vs_params = shader.VsParams{
// rowmath では vec * mat の乗算順なので view_projection
// glsl では mat * vec の乗算順なので projection_view
Expand All @@ -235,17 +265,21 @@ fn draw_mesh(self: *const @This(), mesh_index: u32, vp: Mat4, model: Mat4) void
};
sg.applyUniforms(.FS, shader.SLOT_fs_params, sg.asRange(&fs_params));

const mesh = &self.meshes[mesh_index];
sg.applyBindings(mesh.bind);
var mesh = &self.meshes[mesh_index];

var offset: u32 = 0;
for (mesh.submeshes) |submesh| {
for (mesh.submeshes) |*submesh| {
sg.applyUniforms(
.FS,
shader.SLOT_submesh_params,
sg.asRange(&submesh.submesh_params),
);

mesh.bind.fs = submesh.color_texture.fs;
sg.applyBindings(mesh.bind);

sg.draw(offset, submesh.draw_count, 1);

offset += submesh.draw_count;
}
}
11 changes: 10 additions & 1 deletion deps/sokol_samples/sample_framework/gltf.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ uniform vs_params {

in vec3 aPos;
in vec3 aNormal;
in vec2 aTexCoord;

out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;

void main() {
gl_Position = projection_view * model * vec4(aPos, 1.0);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = aNormal;
TexCoord = aTexCoord;
}
@end

Expand All @@ -25,16 +28,22 @@ uniform submesh_params {
vec4 material_rgba;
};

uniform texture2D colorTexture2D;
uniform sampler colorTextureSmp;
#define colorTexture sampler2D(colorTexture2D, colorTextureSmp)

in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;
out vec4 frag_color;

void main() {
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec4 texel = texture(colorTexture, TexCoord);
// vec3 diffuse = diff * lightColor;
frag_color = vec4(
frag_color = texel * vec4(
material_rgba.r * diff,
material_rgba.g * diff,
material_rgba.b * diff,
Expand Down
1 change: 1 addition & 0 deletions deps/sokol_samples/sample_framework/main.zig
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub usingnamespace @import("Scene.zig");
pub const gltf_fetcher = @import("gltf_fetcher.zig");
pub const stb = @import("stb/stb.zig");
6 changes: 6 additions & 0 deletions deps/sokol_samples/sample_framework/stb/image.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// flip the image vertically, so the first pixel in the output array is the bottom left
pub extern "c" fn stbi_set_flip_vertically_on_load(flag_true_if_should_flip: c_int) void;

pub extern "c" fn stbi_load_from_memory(buffer: [*c]const u8, len: c_int, x: *c_int, y: *c_int, comp: *c_int, req_comp: c_int) [*c]const u8;

pub extern "c" fn stbi_image_free(retval_from_stbi_load: *const anyopaque) void;
2 changes: 2 additions & 0 deletions deps/sokol_samples/sample_framework/stb/stb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
1 change: 1 addition & 0 deletions deps/sokol_samples/sample_framework/stb/stb.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const image = @import("image.zig");
15 changes: 13 additions & 2 deletions deps/zigltf/src/GltfBuffer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,23 @@ pub fn init(
};
}

pub fn deinit(self:*@This())void
{
pub fn deinit(self: *@This()) void {
// TODO:
self.uriMap.deinit();
}

pub fn getImageBytes(self: *@This(), image_index: u32) ![]const u8 {
const image = self.gltf.images[image_index];
if (image.bufferView) |bufferView_index| {
return try self.getBufferViewBytes(bufferView_index);
} else if (image.uri) |uri| {
_ = uri;
@panic("image.uri not implemented");
} else {
unreachable;
}
}

pub fn getAccessorBytes(self: *@This(), T: type, accessor_index: u32) ![]const T {
const accessor = self.gltf.accessors[accessor_index];
std.debug.assert(@sizeOf(T) == accessor.stride());
Expand Down
14 changes: 11 additions & 3 deletions deps/zigltf/src/types/Mesh.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ pub const Mesh = @This();
const Attributes = struct {
POSITION: u32,
NORMAL: ?u32 = null,
TANGENT: ?u32 = null,
TEXCOORD_0: ?u32 = null,
COLOR_0: ?u32 = null,
JOINTS_0: ?u32 = null,
WEIGHTS_0: ?u32 = null,

pub fn format(
self: @This(),
Expand All @@ -17,9 +22,12 @@ const Attributes = struct {
// if (self.POSITION) |POSITION| {
try writer.print("[POS=>#{}]", .{self.POSITION});
// }
if (self.NORMAL) |NORMAL| {
try writer.print("[NOM=>#{}]", .{NORMAL});
}
if (self.NORMAL) |NORMAL| try writer.print("[NOM=>#{}]", .{NORMAL});
if (self.TANGENT) |TANGENT| try writer.print("[NOM=>#{}]", .{TANGENT});
if (self.TEXCOORD_0) |TEXCOORD_0| try writer.print("[NOM=>#{}]", .{TEXCOORD_0});
if (self.COLOR_0) |COLOR_0| try writer.print("[NOM=>#{}]", .{COLOR_0});
if (self.JOINTS_0) |JOINTS_0| try writer.print("[NOM=>#{}]", .{JOINTS_0});
if (self.WEIGHTS_0) |WEIGHTS_0| try writer.print("[NOM=>#{}]", .{WEIGHTS_0});
}
};

Expand Down

0 comments on commit abb658a

Please sign in to comment.