Skip to content

Commit

Permalink
add viewport support
Browse files Browse the repository at this point in the history
  • Loading branch information
szabolcsdombi committed Oct 24, 2021
1 parent 8adbebd commit b020841
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 13 deletions.
66 changes: 66 additions & 0 deletions examples/viewports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import zengl

from window import Window

window = Window(1280, 720)
ctx = zengl.instance(zengl.context())

window.set_caption('Hello World | Vendor: %s | Renderer: %s | Version: %s' % ctx.info)

image = ctx.image(window.size, 'rgba8unorm', samples=4)

triangle = ctx.renderer(
vertex_shader='''
#version 330
out vec3 v_color;
vec2 positions[3] = vec2[](
vec2(0.0, 0.8),
vec2(-0.6, -0.8),
vec2(0.6, -0.8)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0);
v_color = colors[gl_VertexID];
}
''',
fragment_shader='''
#version 330
in vec3 v_color;
layout (location = 0) out vec4 out_color;
void main() {
out_color = vec4(v_color, 1.0);
}
''',
framebuffer=[image],
topology='triangles',
vertex_count=3,
)


@window.render
def render():
image.clear(1.0, 1.0, 1.0, 1.0)
triangle.viewport = (0, 0, 640, 360)
triangle.render()
triangle.viewport = (0, 360, 640, 360)
triangle.render()
triangle.viewport = (640, 0, 640, 360)
triangle.render()
triangle.viewport = (640, 360, 640, 360)
triangle.render()
image.blit()


window.run()
52 changes: 39 additions & 13 deletions zengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ struct Instance {
DescriptorSetBuffers * current_buffers;
DescriptorSetImages * current_images;
GlobalSettings * current_global_settings;
Viewport viewport;
int current_framebuffer;
int current_program;
int current_vertex_array;
int viewport_width;
int viewport_height;
int default_texture_unit;
GLMethods gl;
};
Expand Down Expand Up @@ -98,8 +97,7 @@ struct Renderer {
int vertex_count;
int instance_count;
int index_type;
int framebuffer_width;
int framebuffer_height;
Viewport viewport;
DescriptorSetBuffers * descriptor_set_buffers;
DescriptorSetImages * descriptor_set_images;
GlobalSettings * global_settings;
Expand Down Expand Up @@ -477,8 +475,7 @@ Instance * meth_instance(PyObject * self, PyObject * vargs, PyObject * kwargs) {
res->current_framebuffer = 0;
res->current_program = 0;
res->current_vertex_array = 0;
res->viewport_width = -1;
res->viewport_height = -1;
res->viewport = {};
res->default_texture_unit = default_texture_unit;
res->gl = gl;
return res;
Expand Down Expand Up @@ -748,6 +745,7 @@ Renderer * Instance_meth_renderer(Instance * self, PyObject * vargs, PyObject *
"stencil",
"blending",
"polygon_offset",
"viewport",
NULL,
};

Expand All @@ -772,11 +770,12 @@ Renderer * Instance_meth_renderer(Instance * self, PyObject * vargs, PyObject *
PyObject * stencil = Py_False;
PyObject * blending = Py_False;
PyObject * polygon_offset = Py_False;
PyObject * viewport = Py_None;

int args_ok = PyArg_ParseTupleAndKeywords(
vargs,
kwargs,
"|$OOOsOOOOiipOOOOOOOOOO",
"|$OOOsOOOOiipOOOOOOOOOOO",
keywords,
&vertex_shader,
&fragment_shader,
Expand All @@ -798,7 +797,8 @@ Renderer * Instance_meth_renderer(Instance * self, PyObject * vargs, PyObject *
&depth,
&stencil,
&blending,
&polygon_offset
&polygon_offset,
&viewport
);

if (!args_ok) {
Expand Down Expand Up @@ -934,7 +934,15 @@ Renderer * Instance_meth_renderer(Instance * self, PyObject * vargs, PyObject *
DescriptorSetImages * descriptor_set_images = build_descriptor_set_images(self, sampler_bindings);
GlobalSettings * global_settings = build_global_settings(self, settings);

Image * first_image = (Image *)PySequence_GetItem(framebuffer_images, 0);
Viewport viewport_value = to_viewport(viewport);
if (!viewport_value.viewport) {
if (PyErr_Occurred()) {
return NULL;
}
Image * first_image = (Image *)PySequence_GetItem(framebuffer_images, 0);
viewport_value.width = (short)first_image->width;
viewport_value.height = (short)first_image->height;
}

Renderer * res = PyObject_New(Renderer, self->module_state->Renderer_type);
res->instance = self;
Expand All @@ -945,8 +953,7 @@ Renderer * Instance_meth_renderer(Instance * self, PyObject * vargs, PyObject *
res->vertex_count = vertex_count;
res->instance_count = instance_count;
res->index_type = index_type;
res->framebuffer_width = first_image->width;
res->framebuffer_height = first_image->height;
res->viewport = viewport_value;
res->descriptor_set_buffers = descriptor_set_buffers;
res->descriptor_set_images = descriptor_set_images;
res->global_settings = global_settings;
Expand Down Expand Up @@ -1267,8 +1274,8 @@ PyObject * Image_meth_blit(Image * self, PyObject * vargs, PyObject * kwargs) {

PyObject * Renderer_meth_render(Renderer * self) {
const GLMethods & gl = self->instance->gl;
if (self->framebuffer_width != self->instance->viewport_width || self->framebuffer_height != self->instance->viewport_height) {
gl.Viewport(0, 0, self->framebuffer_width, self->framebuffer_height);
if (self->viewport.viewport != self->instance->viewport.viewport) {
gl.Viewport(self->viewport.x, self->viewport.y, self->viewport.width, self->viewport.height);
}
bind_global_settings(self->instance, self->global_settings);
bind_framebuffer(self->instance, self->framebuffer);
Expand All @@ -1284,6 +1291,19 @@ PyObject * Renderer_meth_render(Renderer * self) {
Py_RETURN_NONE;
}

PyObject * Renderer_get_viewport(Renderer * self) {
return Py_BuildValue("iiii", self->viewport.x, self->viewport.y, self->viewport.width, self->viewport.height);
}

int Renderer_set_viewport(Renderer * self, PyObject * viewport) {
Viewport viewport_value = to_viewport(viewport);
if (!viewport_value.viewport) {
return -1;
}
self->viewport = viewport_value;
return 0;
}

struct vec3 {
double x, y, z;
};
Expand Down Expand Up @@ -1556,6 +1576,11 @@ PyMethodDef Renderer_methods[] = {
{},
};

PyGetSetDef Renderer_getset[] = {
{"viewport", (getter)Renderer_get_viewport, (setter)Renderer_set_viewport, NULL, NULL},
{},
};

PyMemberDef Renderer_members[] = {
{"vertex_count", T_OBJECT_EX, offsetof(Renderer, vertex_count), 0, NULL},
{"instance_count", T_OBJECT_EX, offsetof(Renderer, instance_count), 0, NULL},
Expand Down Expand Up @@ -1585,6 +1610,7 @@ PyType_Slot Image_slots[] = {

PyType_Slot Renderer_slots[] = {
{Py_tp_methods, Renderer_methods},
{Py_tp_getset, Renderer_getset},
{Py_tp_members, Renderer_members},
{Py_tp_dealloc, default_dealloc},
{},
Expand Down
34 changes: 34 additions & 0 deletions zengl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,16 @@ struct StencilSettings {
int reference;
};

union Viewport {
unsigned long long viewport;
struct {
short x;
short y;
short width;
short height;
};
};

VertexFormat get_vertex_format(const char * format) {
if (!strcmp(format, "uint8x2")) return {GL_UNSIGNED_BYTE, 2, false, true};
if (!strcmp(format, "uint8x4")) return {GL_UNSIGNED_BYTE, 4, false, true};
Expand Down Expand Up @@ -476,6 +486,30 @@ PyObject * to_str(const unsigned char * ptr) {
return PyUnicode_FromString((char *)ptr);
}

Viewport to_viewport(PyObject * obj) {
Viewport res = {};
if (obj == Py_None) {
return res;
}
PyObject * seq = PySequence_Fast(obj, "viewport is not iterable");
if (!seq) {
return res;
}
int size = (int)PySequence_Size(seq);
if (size != 2 && size != 4) {
return res;
}
PyObject ** items = PySequence_Fast_ITEMS(seq);
res.x = (short)PyLong_AsLong(items[0]);
res.y = (short)PyLong_AsLong(items[1]);
res.width = (short)PyLong_AsLong(items[2]);
res.height = (short)PyLong_AsLong(items[3]);
if (PyErr_Occurred()) {
return res;
}
return res;
}

void * load_method(PyObject * context, const char * method) {
PyObject * res = PyObject_CallMethod(context, "load", "s", method);
if (!res) {
Expand Down

0 comments on commit b020841

Please sign in to comment.