glClear is causing stack corrpution
This commit is contained in:
		 Submodule lib/Catch2 updated: a8cf3e6710...32d9ae24bc
									
								
							
							
								
								
									
										2
									
								
								lib/SDL
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/SDL
									
									
									
									
									
								
							 Submodule lib/SDL updated: ac6b32bb02...4722269fb6
									
								
							 Submodule lib/freetype updated: dc519d06ea...e969289f88
									
								
							
							
								
								
									
										2
									
								
								lib/glfw
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/glfw
									
									
									
									
									
								
							 Submodule lib/glfw updated: 3eaf1255b2...a87acd8c1f
									
								
							
							
								
								
									
										2
									
								
								lib/glm
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/glm
									
									
									
									
									
								
							 Submodule lib/glm updated: 47585fde0c...586a402397
									
								
							 Submodule lib/openal-soft updated: 6420bc86cd...d6d572df66
									
								
							@@ -12,7 +12,7 @@
 | 
			
		||||
#include "component/display/MeshRenderer.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  struct IRenderPass {
 | 
			
		||||
  class IRenderPass {
 | 
			
		||||
    public:
 | 
			
		||||
      std::shared_ptr<Mesh> mesh;
 | 
			
		||||
 | 
			
		||||
@@ -43,14 +43,17 @@ namespace Dawn {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template<class S, typename D>
 | 
			
		||||
  struct RenderPass : public IRenderPass {
 | 
			
		||||
  class RenderPass : public IRenderPass {
 | 
			
		||||
    private:
 | 
			
		||||
      std::shared_ptr<S> shader;
 | 
			
		||||
      const D data;
 | 
			
		||||
      const std::unordered_map<
 | 
			
		||||
        shadertexturebinding_t, std::shared_ptr<Texture>
 | 
			
		||||
      > &textures;
 | 
			
		||||
      std::shared_ptr<Mesh> mesh;
 | 
			
		||||
      const enum MeshDrawMode drawMode;
 | 
			
		||||
      const int32_t indiceStart;
 | 
			
		||||
      const int32_t indiceCount;
 | 
			
		||||
      const D data;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      /**
 | 
			
		||||
@@ -66,12 +69,16 @@ namespace Dawn {
 | 
			
		||||
      RenderPass(
 | 
			
		||||
        SceneComponent &self,
 | 
			
		||||
        const D d,
 | 
			
		||||
        const std::unordered_map<
 | 
			
		||||
          shadertexturebinding_t, std::shared_ptr<Texture>
 | 
			
		||||
        > textures,
 | 
			
		||||
        const std::shared_ptr<Mesh> mesh,
 | 
			
		||||
        const enum MeshDrawMode drawMode,
 | 
			
		||||
        const int32_t indiceStart,
 | 
			
		||||
        const int32_t indiceCount
 | 
			
		||||
      ) :
 | 
			
		||||
        data(d),
 | 
			
		||||
        textures(textures),
 | 
			
		||||
        mesh(mesh),
 | 
			
		||||
        drawMode(drawMode),
 | 
			
		||||
        indiceStart(indiceStart),
 | 
			
		||||
@@ -91,6 +98,7 @@ namespace Dawn {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void bind() override {
 | 
			
		||||
        std::cout << "textures: " << textures.size() << "\n";
 | 
			
		||||
        shader->bind();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -99,6 +107,10 @@ namespace Dawn {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void upload() override {
 | 
			
		||||
        for(auto &pair : textures) {
 | 
			
		||||
          assertNotNull(pair.second, "Texture cannot be null!");
 | 
			
		||||
          pair.second->bind(pair.first);
 | 
			
		||||
        }
 | 
			
		||||
        shader->upload();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -139,17 +151,21 @@ namespace Dawn {
 | 
			
		||||
   * @return Created render pass.
 | 
			
		||||
   */
 | 
			
		||||
  template<class S, typename D>
 | 
			
		||||
  std::shared_ptr<struct IRenderPass> createRenderPass(
 | 
			
		||||
  std::shared_ptr<IRenderPass> createRenderPass(
 | 
			
		||||
    SceneComponent &self,
 | 
			
		||||
    const D data,
 | 
			
		||||
    const std::unordered_map<
 | 
			
		||||
      shadertexturebinding_t, std::shared_ptr<Texture>
 | 
			
		||||
    > textures = {},
 | 
			
		||||
    const std::shared_ptr<Mesh> mesh = nullptr,
 | 
			
		||||
    const enum MeshDrawMode drawMode = MeshDrawMode::TRIANGLES,
 | 
			
		||||
    int32_t indiceStart = 0,
 | 
			
		||||
    int32_t indiceCount = -1
 | 
			
		||||
  ) {
 | 
			
		||||
    return std::make_shared<struct RenderPass<S,D>>(
 | 
			
		||||
    return std::make_shared<RenderPass<S,D>>(
 | 
			
		||||
      self,
 | 
			
		||||
      data,
 | 
			
		||||
      textures,
 | 
			
		||||
      mesh,
 | 
			
		||||
      drawMode,
 | 
			
		||||
      indiceStart,
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,16 @@ struct Color SimpleTexturedMaterial::getColor() {
 | 
			
		||||
  return this->data.color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SimpleTexturedMaterial::setColor(struct Color color) {
 | 
			
		||||
std::shared_ptr<Texture> SimpleTexturedMaterial::getTexture() {
 | 
			
		||||
  return this->texture;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SimpleTexturedMaterial::setTexture(std::shared_ptr<Texture> texture) {
 | 
			
		||||
  this->texture = texture;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void SimpleTexturedMaterial::setColor(const struct Color color) {
 | 
			
		||||
  this->data.color = color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -22,11 +31,23 @@ std::vector<std::shared_ptr<IRenderPass>> SimpleTexturedMaterial::getPasses(
 | 
			
		||||
  this->data.projection = ctx.camera->getProjection();
 | 
			
		||||
  this->data.view = ctx.camera->getItem()->getWorldTransform();
 | 
			
		||||
  this->data.color = COLOR_RED;
 | 
			
		||||
  auto textures = std::unordered_map<
 | 
			
		||||
    shadertexturebinding_t, std::shared_ptr<Texture>
 | 
			
		||||
  >();
 | 
			
		||||
  
 | 
			
		||||
  if(this->texture) {
 | 
			
		||||
    this->data.hasTexture = true;
 | 
			
		||||
    this->data.texture = 0;
 | 
			
		||||
    textures[this->data.texture] = this->texture;
 | 
			
		||||
  } else {
 | 
			
		||||
    this->data.hasTexture = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    createRenderPass<SimpleTexturedShader, struct SimpleTexturedShaderData>(
 | 
			
		||||
      *this,
 | 
			
		||||
      data
 | 
			
		||||
      data,
 | 
			
		||||
      textures
 | 
			
		||||
    )
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,13 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "component/display/material/Material.hpp"
 | 
			
		||||
#include "display/shader/SimpleTexturedShader.hpp"
 | 
			
		||||
#include "display/Texture.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  class SimpleTexturedMaterial : public Material {
 | 
			
		||||
    private:
 | 
			
		||||
      struct SimpleTexturedShaderData data;
 | 
			
		||||
      std::shared_ptr<Texture> texture;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      /**
 | 
			
		||||
@@ -18,12 +20,26 @@ namespace Dawn {
 | 
			
		||||
       */
 | 
			
		||||
      struct Color getColor();
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Returns the texture of this material.
 | 
			
		||||
       * 
 | 
			
		||||
       * @return The texture of this material.
 | 
			
		||||
       */
 | 
			
		||||
      std::shared_ptr<Texture> getTexture();
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Sets the texture of this material.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param texture The texture to set.
 | 
			
		||||
       */
 | 
			
		||||
      void setTexture(std::shared_ptr<Texture> texture);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Sets the color of this material.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param color The color to set.
 | 
			
		||||
       */
 | 
			
		||||
      void setColor(struct Color color);
 | 
			
		||||
      void setColor(const struct Color color);
 | 
			
		||||
 | 
			
		||||
      std::vector<std::shared_ptr<IRenderPass>> getPasses(
 | 
			
		||||
        struct RenderPassContext &ctx
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								src/dawn/display/ITexture.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/dawn/display/ITexture.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
// Copyright (c) 2023 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "display/Color.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  enum TextureFormat {
 | 
			
		||||
    TEXTURE_FORMAT_R = 1,
 | 
			
		||||
    TEXTURE_FORMAT_RG = 2,
 | 
			
		||||
    TEXTURE_FORMAT_RGB = 3,
 | 
			
		||||
    TEXTURE_FORMAT_RGBA = 4
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  enum TextureWrapMode {
 | 
			
		||||
    TEXTURE_WRAP_MODE_REPEAT = 0,
 | 
			
		||||
    TEXTURE_WRAP_MODE_MIRRORED_REPEAT = 1,
 | 
			
		||||
    TEXTURE_WRAP_MODE_CLAMP_TO_EDGE = 2,
 | 
			
		||||
    TEXTURE_WRAP_MODE_CLAMP_TO_BORDER = 3
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  enum TextureFilterMode {
 | 
			
		||||
    TEXTURE_FILTER_MODE_NEAREST = 0,
 | 
			
		||||
    TEXTURE_FILTER_MODE_LINEAR = 1
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  enum TextureDataFormat {
 | 
			
		||||
    TEXTURE_DATA_FORMAT_UNSIGNED_BYTE = 0,
 | 
			
		||||
    TEXTURE_DATA_FORMAT_FLOAT = 1
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  class ITexture {
 | 
			
		||||
    public:
 | 
			
		||||
      enum TextureWrapMode wrapModeX = TEXTURE_WRAP_MODE_REPEAT;
 | 
			
		||||
      enum TextureWrapMode wrapModeY = TEXTURE_WRAP_MODE_REPEAT;
 | 
			
		||||
      enum TextureFilterMode filterModeMin = TEXTURE_FILTER_MODE_NEAREST;
 | 
			
		||||
      enum TextureFilterMode filterModeMag = TEXTURE_FILTER_MODE_NEAREST;
 | 
			
		||||
      enum TextureFilterMode mipMapFilterModeMin = TEXTURE_FILTER_MODE_NEAREST;
 | 
			
		||||
      enum TextureFilterMode mipMapFilterModeMag = TEXTURE_FILTER_MODE_NEAREST;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Returns the width of the texture.
 | 
			
		||||
       * 
 | 
			
		||||
       * @return Width of the texture.
 | 
			
		||||
       */
 | 
			
		||||
      virtual int32_t getWidth() = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Returns the height of the texture.
 | 
			
		||||
       * 
 | 
			
		||||
       * @return Height of the texture.
 | 
			
		||||
       */
 | 
			
		||||
      virtual int32_t getHeight() = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Initializes a texture.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param width Width of the texture (in pixels).
 | 
			
		||||
       * @param height Height of the texture (in pixels).
 | 
			
		||||
       * @param format Data format of the texture to use.
 | 
			
		||||
       * @param dataFormat Data format of the texture to use.
 | 
			
		||||
       */
 | 
			
		||||
      virtual void setSize(
 | 
			
		||||
        const int32_t width,
 | 
			
		||||
        const int32_t height,
 | 
			
		||||
        const enum TextureFormat format,
 | 
			
		||||
        const enum TextureDataFormat dataFormat
 | 
			
		||||
      ) = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Returns true only when the texture has been loaded, sized and put on
 | 
			
		||||
       * the gpu for rendering.
 | 
			
		||||
       * 
 | 
			
		||||
       * @return True if ready, otherwise false.
 | 
			
		||||
       */
 | 
			
		||||
      // virtual bool_t isReady() = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Buffer pixel data onto the GPU. Pixel buffering is rather costly so
 | 
			
		||||
       * avoid doing this too often.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param pixels Array of pixels you're trying to buffer.
 | 
			
		||||
       */
 | 
			
		||||
      virtual void buffer(const struct ColorU8 pixels[]) = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Buffer pixel data onto the GPU. Pixel buffering is rather costly so
 | 
			
		||||
       * avoid doing this too often.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param pixels Array of pixels you're trying to buffer.
 | 
			
		||||
       */
 | 
			
		||||
      virtual void buffer(const uint8_t pixels[]) = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Binds the texture to the given slot (for use by the shaders).
 | 
			
		||||
       * 
 | 
			
		||||
       * @param slot Slot to bind to.
 | 
			
		||||
       */
 | 
			
		||||
      virtual void bind(const uint8_t slot) = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Disposes of the texture.
 | 
			
		||||
       */
 | 
			
		||||
      virtual ~ITexture() {
 | 
			
		||||
      }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -68,6 +68,7 @@ void RenderPipeline::renderSceneCamera(
 | 
			
		||||
  assertNotNull(game, "Game cannot be null");
 | 
			
		||||
  assertNotNull(scene, "Scene cannot be null"); 
 | 
			
		||||
  assertNotNull(camera, "Camera cannot be null");
 | 
			
		||||
  assertNotNull(renderTarget, "RenderTarget cannot be null");
 | 
			
		||||
 | 
			
		||||
  struct RenderPassContext ctx = {
 | 
			
		||||
    game,
 | 
			
		||||
@@ -77,14 +78,15 @@ void RenderPipeline::renderSceneCamera(
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Get list of renderables
 | 
			
		||||
  std::vector<std::shared_ptr<struct IRenderPass>> renderPasses;
 | 
			
		||||
  std::vector<std::shared_ptr<IRenderPass>> renderPasses;
 | 
			
		||||
  auto renderables = scene->findComponents<IRenderableComponent>();
 | 
			
		||||
  for(auto renderable : renderables) {
 | 
			
		||||
    auto rp = renderable->getPasses(ctx);
 | 
			
		||||
    renderPasses.insert(renderPasses.end(), rp.begin(), rp.end());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Sort the render passes
 | 
			
		||||
  auto rp = renderPasses[0];
 | 
			
		||||
  rp->bind();
 | 
			
		||||
  
 | 
			
		||||
  // TODO: Make clearing the buffers editable!
 | 
			
		||||
  renderTarget->bind();
 | 
			
		||||
@@ -92,17 +94,15 @@ void RenderPipeline::renderSceneCamera(
 | 
			
		||||
    RENDER_TARGET_CLEAR_COLOR |
 | 
			
		||||
    RENDER_TARGET_CLEAR_DEPTH
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  rp->bind();
 | 
			
		||||
  
 | 
			
		||||
  std::for_each(
 | 
			
		||||
    renderPasses.begin(),
 | 
			
		||||
    renderPasses.end(),
 | 
			
		||||
    [&](std::shared_ptr<struct IRenderPass> pass) {
 | 
			
		||||
      pass->bind();
 | 
			
		||||
      pass->setData();
 | 
			
		||||
      pass->upload();
 | 
			
		||||
      pass->draw();
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
  for(auto renderPass : renderPasses) {
 | 
			
		||||
    renderPass->bind();
 | 
			
		||||
    renderPass->setData();
 | 
			
		||||
    renderPass->upload();
 | 
			
		||||
    renderPass->draw();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RenderPipeline::~RenderPipeline() {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "event/Event.hpp"
 | 
			
		||||
 | 
			
		||||
#define RENDER_TARGET_CLEAR_COLOR 1 << 0
 | 
			
		||||
#define RENDER_TARGET_CLEAR_DEPTH 1 << 1
 | 
			
		||||
#define RENDER_TARGET_CLEAR_COLOR (1 << 0)
 | 
			
		||||
#define RENDER_TARGET_CLEAR_DEPTH (1 << 1)
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  class RenderTarget {
 | 
			
		||||
 
 | 
			
		||||
@@ -123,6 +123,12 @@ glm::quat SceneItemTransform::getLocalRotation() {
 | 
			
		||||
  return this->localRotation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SceneItemTransform::setLocalTransform(const glm::mat4 transform) {
 | 
			
		||||
  this->transformLocal = transform;
 | 
			
		||||
  this->updateLocalValuesFromLocalTransform();
 | 
			
		||||
  this->updateWorldTransformFromLocalTransform();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SceneItemTransform::setWorldTransform(const glm::mat4 transform) {
 | 
			
		||||
  this->transformWorld = transform;
 | 
			
		||||
  this->updateLocalTransformFromWorldTransform();
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,13 @@ namespace Dawn {
 | 
			
		||||
       * @return Local rotation of this item.
 | 
			
		||||
       */
 | 
			
		||||
      glm::quat getLocalRotation();
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Sets the transform of this item within local space (relative to parent)
 | 
			
		||||
       * 
 | 
			
		||||
       * @param transform Transform of this item in local space.
 | 
			
		||||
       */
 | 
			
		||||
      void setLocalTransform(const glm::mat4 transform);
 | 
			
		||||
      
 | 
			
		||||
      /**
 | 
			
		||||
       * Sets the transform of this item within world space (relative to scene
 | 
			
		||||
 
 | 
			
		||||
@@ -27,11 +27,11 @@ void Dawn::helloWorldScene(Scene &s) {
 | 
			
		||||
  auto cubeMeshRenderer = cubeItem->addComponent<MeshRenderer>();
 | 
			
		||||
  cubeMeshRenderer->mesh = cubeMesh;
 | 
			
		||||
  auto cubeMaterial = cubeItem->addComponent<SimpleTexturedMaterial>();
 | 
			
		||||
  addSimpleComponent(cubeItem, [](auto &cmp, auto &events) {
 | 
			
		||||
    events.push_back(cmp.getScene()->onUnpausedUpdate.listen([&](float_t delta) {
 | 
			
		||||
      auto item = cmp.getItem();
 | 
			
		||||
      item->setLocalRotation(item->getLocalRotation() * glm::quat(glm::vec3(1, 1, 0) * delta));
 | 
			
		||||
      // item->setLocalScale(item->getLocalScale() + glm::vec3(1, 1, 1) * delta);
 | 
			
		||||
    }));
 | 
			
		||||
  });
 | 
			
		||||
  // addSimpleComponent(cubeItem, [](auto &cmp, auto &events) {
 | 
			
		||||
  //   events.push_back(cmp.getScene()->onUnpausedUpdate.listen([&](float_t delta) {
 | 
			
		||||
  //     auto item = cmp.getItem();
 | 
			
		||||
  //     item->setLocalRotation(item->getLocalRotation() * glm::quat(glm::vec3(1, 1, 0) * delta));
 | 
			
		||||
  //     // item->setLocalScale(item->getLocalScale() + glm::vec3(1, 1, 1) * delta);
 | 
			
		||||
  //   }));
 | 
			
		||||
  // });
 | 
			
		||||
}
 | 
			
		||||
@@ -45,13 +45,14 @@ void BackBufferRenderTarget::setClearColor(const struct Color color) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BackBufferRenderTarget::clear(const int32_t clearFlags) {
 | 
			
		||||
  glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
 | 
			
		||||
  glClearColor(clearColor.r, clearColor.g, clearColor.b, 1.0f);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
 | 
			
		||||
  GLbitfield mask = 0;
 | 
			
		||||
  if(Flag::isOn(clearFlags, RENDER_TARGET_CLEAR_COLOR)) {
 | 
			
		||||
    mask |= GL_COLOR_BUFFER_BIT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if(Flag::isOn(clearFlags, RENDER_TARGET_CLEAR_DEPTH)) {
 | 
			
		||||
    mask |= GL_DEPTH_BUFFER_BIT;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
target_sources(${DAWN_TARGET_NAME}
 | 
			
		||||
  PRIVATE
 | 
			
		||||
    BackBufferRenderTarget.cpp
 | 
			
		||||
    Texture.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Subdirs
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										208
									
								
								src/dawnopengl/display/Texture.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								src/dawnopengl/display/Texture.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,208 @@
 | 
			
		||||
// Copyright (c) 2022 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#include "assert/assert.hpp"
 | 
			
		||||
#include "assert/assertgl.hpp"
 | 
			
		||||
#include "Texture.hpp"
 | 
			
		||||
 | 
			
		||||
using namespace Dawn;
 | 
			
		||||
 | 
			
		||||
void Texture::bind(const uint8_t slot) {
 | 
			
		||||
  assertTrue(this->id != -1, "Texture is not ready!");
 | 
			
		||||
  glActiveTexture(GL_TEXTURE0 + slot);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
  glBindTexture(GL_TEXTURE_2D, this->id);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
  this->updateTextureProperties();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t Texture::getWidth() {
 | 
			
		||||
  return this->width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t Texture::getHeight() {
 | 
			
		||||
  return this->height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Texture::setSize(
 | 
			
		||||
  const int32_t width,
 | 
			
		||||
  const int32_t height,
 | 
			
		||||
  const enum TextureFormat format,
 | 
			
		||||
  const enum TextureDataFormat dataFormat
 | 
			
		||||
) {
 | 
			
		||||
  if(this->id != -1) {
 | 
			
		||||
    glDeleteTextures(1, &this->id);
 | 
			
		||||
    assertNoGLError();
 | 
			
		||||
    this->id = -1;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  int32_t maxSize;
 | 
			
		||||
  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
 | 
			
		||||
  assertTrue(width > 0 && width <= maxSize, "Width is out of bounds!");
 | 
			
		||||
  assertTrue(height > 0 && height <= maxSize, "Height is out of bounds!");
 | 
			
		||||
 | 
			
		||||
  this->width = width;
 | 
			
		||||
  this->height = height;
 | 
			
		||||
  this->format = format;
 | 
			
		||||
  this->dataFormat = dataFormat;
 | 
			
		||||
 | 
			
		||||
  glGenTextures(1, &this->id);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
  if(this->id <= 0) assertUnreachable("Texture generation failed!");
 | 
			
		||||
 | 
			
		||||
  // Initialize the texture to blank
 | 
			
		||||
  glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
  this->bufferRaw(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bool_t Texture::isReady() {
 | 
			
		||||
//   return this->id != -1;
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
void Texture::updateTextureProperties() {
 | 
			
		||||
  auto setWrapMode = [&](GLenum axis, enum TextureWrapMode wm) {
 | 
			
		||||
    switch(wm) {
 | 
			
		||||
      case TEXTURE_WRAP_MODE_REPEAT:
 | 
			
		||||
        glTexParameteri(GL_TEXTURE_2D, axis, GL_REPEAT);
 | 
			
		||||
        break;
 | 
			
		||||
      
 | 
			
		||||
      case TEXTURE_WRAP_MODE_MIRRORED_REPEAT:
 | 
			
		||||
        glTexParameteri(GL_TEXTURE_2D, axis, GL_MIRRORED_REPEAT);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case TEXTURE_WRAP_MODE_CLAMP_TO_EDGE:
 | 
			
		||||
        glTexParameteri(GL_TEXTURE_2D, axis, GL_CLAMP_TO_EDGE);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case TEXTURE_WRAP_MODE_CLAMP_TO_BORDER:
 | 
			
		||||
        glTexParameteri(GL_TEXTURE_2D, axis, GL_CLAMP_TO_BORDER);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
        assertUnreachable("Unknown wrap mode!");
 | 
			
		||||
    }
 | 
			
		||||
    assertNoGLError();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  setWrapMode(GL_TEXTURE_WRAP_S, this->wrapModeX);
 | 
			
		||||
  setWrapMode(GL_TEXTURE_WRAP_T, this->wrapModeY);
 | 
			
		||||
 | 
			
		||||
  auto setFilterMode = [&](
 | 
			
		||||
    GLenum minMag,
 | 
			
		||||
    enum TextureFilterMode filter,
 | 
			
		||||
    enum TextureFilterMode mapFilterMode
 | 
			
		||||
  ) {
 | 
			
		||||
    switch(filter) {
 | 
			
		||||
      case TEXTURE_FILTER_MODE_NEAREST: {
 | 
			
		||||
        glTexParameteri(GL_TEXTURE_2D, minMag, GL_NEAREST);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      case TEXTURE_FILTER_MODE_LINEAR: {
 | 
			
		||||
        glTexParameteri(GL_TEXTURE_2D, minMag, GL_LINEAR);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      default: {
 | 
			
		||||
        assertUnreachable("Unknown filter mode!");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    assertNoGLError();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  setFilterMode(
 | 
			
		||||
    GL_TEXTURE_MIN_FILTER, this->filterModeMin, this->mipMapFilterModeMin
 | 
			
		||||
  );
 | 
			
		||||
  setFilterMode(
 | 
			
		||||
    GL_TEXTURE_MAG_FILTER, this->filterModeMag, this->mipMapFilterModeMag
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Texture::bufferRaw(const void *data) {
 | 
			
		||||
  assertTrue(this->id != -1, "Texture is not ready!");
 | 
			
		||||
 | 
			
		||||
  GLenum format;
 | 
			
		||||
  switch(this->format) {
 | 
			
		||||
    case TEXTURE_FORMAT_R:
 | 
			
		||||
      format = GL_RED;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case TEXTURE_FORMAT_RG:
 | 
			
		||||
      format = GL_RG;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case TEXTURE_FORMAT_RGB:
 | 
			
		||||
      format = GL_RGB;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case TEXTURE_FORMAT_RGBA:
 | 
			
		||||
      format = GL_RGBA;
 | 
			
		||||
      break;
 | 
			
		||||
    
 | 
			
		||||
    default:
 | 
			
		||||
      assertUnreachable("Unknown texture format!");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GLenum dataFormat;
 | 
			
		||||
  switch(this->dataFormat) {
 | 
			
		||||
    case TEXTURE_DATA_FORMAT_UNSIGNED_BYTE:
 | 
			
		||||
      dataFormat = GL_UNSIGNED_BYTE;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case TEXTURE_DATA_FORMAT_FLOAT:
 | 
			
		||||
      dataFormat = GL_FLOAT;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      assertUnreachable("Unknown texture data format!");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  glBindTexture(GL_TEXTURE_2D, this->id);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
  glTexImage2D(
 | 
			
		||||
    GL_TEXTURE_2D, 0, format,
 | 
			
		||||
    this->width, this->height,
 | 
			
		||||
    0, format, dataFormat, data
 | 
			
		||||
  );
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
  glGenerateMipmap(GL_TEXTURE_2D);
 | 
			
		||||
  assertNoGLError();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Texture::buffer(const struct ColorU8 pixels[]) {
 | 
			
		||||
  assertTrue(
 | 
			
		||||
    this->dataFormat == TEXTURE_DATA_FORMAT_UNSIGNED_BYTE,
 | 
			
		||||
    "Texture data format must be unsigned byte!"
 | 
			
		||||
  );
 | 
			
		||||
  this->bufferRaw((void*)pixels);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Texture::buffer(const struct Color pixels[]) {
 | 
			
		||||
  assertTrue(
 | 
			
		||||
    this->dataFormat == TEXTURE_DATA_FORMAT_FLOAT,
 | 
			
		||||
    "Texture data format must be float!"
 | 
			
		||||
  );
 | 
			
		||||
  assertTrue(
 | 
			
		||||
    this->format == TEXTURE_FORMAT_RGBA,
 | 
			
		||||
    "Texture format must be RGBA!"
 | 
			
		||||
  );
 | 
			
		||||
  this->bufferRaw((void*)pixels);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Texture::buffer(const uint8_t pixels[]) {
 | 
			
		||||
  assertTrue(
 | 
			
		||||
    this->dataFormat == TEXTURE_DATA_FORMAT_UNSIGNED_BYTE,
 | 
			
		||||
    "Texture data format must be unsigned byte!"
 | 
			
		||||
  );
 | 
			
		||||
  this->bufferRaw((void*)pixels);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Texture::~Texture() {
 | 
			
		||||
  if(this->id != -1) {
 | 
			
		||||
    glDeleteTextures(1, &this->id);
 | 
			
		||||
    assertNoGLError();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								src/dawnopengl/display/Texture.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/dawnopengl/display/Texture.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
// Copyright (c) 2022 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "dawnopengl.hpp"
 | 
			
		||||
#include "display/ITexture.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  class TextureRenderTarget;
 | 
			
		||||
  
 | 
			
		||||
  typedef GLuint textureslot_t;
 | 
			
		||||
 | 
			
		||||
  class Texture : public ITexture {
 | 
			
		||||
    private:
 | 
			
		||||
      int32_t width = -1;
 | 
			
		||||
      int32_t height = -1;
 | 
			
		||||
      GLuint id = -1;
 | 
			
		||||
      enum TextureFormat format;
 | 
			
		||||
      enum TextureDataFormat dataFormat;
 | 
			
		||||
 | 
			
		||||
      void updateTextureProperties();
 | 
			
		||||
      void bufferRaw(const void *data);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      int32_t getWidth() override;
 | 
			
		||||
      int32_t getHeight() override;
 | 
			
		||||
      void setSize(
 | 
			
		||||
        const int32_t width,
 | 
			
		||||
        const int32_t height,
 | 
			
		||||
        const enum TextureFormat format,
 | 
			
		||||
        const enum TextureDataFormat dataForat
 | 
			
		||||
      ) override;
 | 
			
		||||
      // bool_t isReady() override;
 | 
			
		||||
      void buffer(const struct ColorU8 pixels[]) override;
 | 
			
		||||
      void buffer(const struct Color pixels[]);
 | 
			
		||||
      void buffer(const uint8_t pixels[]) override;
 | 
			
		||||
      void bind(const uint8_t slot) override;
 | 
			
		||||
 | 
			
		||||
      ~Texture();
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -9,8 +9,11 @@
 | 
			
		||||
#include "assert/assert.hpp"
 | 
			
		||||
#include "assert/assertgl.hpp"
 | 
			
		||||
#include "display/Color.hpp"
 | 
			
		||||
#include "display/Texture.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  typedef GLuint shadertexturebinding_t;
 | 
			
		||||
 | 
			
		||||
  enum ShaderOpenGLVariant {
 | 
			
		||||
    GLSL_330_CORE
 | 
			
		||||
  };
 | 
			
		||||
@@ -151,6 +154,18 @@ namespace Dawn {
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                case ShaderParameterType::BOOLEAN: {
 | 
			
		||||
                  auto boolean = (bool_t *)value;
 | 
			
		||||
                  glUniform1i(param.location, *boolean ? 1 : 0);
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                case ShaderParameterType::TEXTURE: {
 | 
			
		||||
                  textureslot_t texture = *((textureslot_t*)value);
 | 
			
		||||
                  glUniform1i(param.location, texture);
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                default: {
 | 
			
		||||
                  assertUnreachable("Unsupported ShaderParameterType");
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -23,11 +23,14 @@ void SimpleTexturedShader::getStages(
 | 
			
		||||
        ShaderStageType::VERTEX,
 | 
			
		||||
        "#version 330 core\n"
 | 
			
		||||
        "layout (location = 0) in vec3 aPos;\n"
 | 
			
		||||
        "layout (location = 1) in vec2 aTexCoord;\n"
 | 
			
		||||
        "uniform mat4 u_Projection;\n"
 | 
			
		||||
        "uniform mat4 u_View;\n"
 | 
			
		||||
        "uniform mat4 u_Model;\n"
 | 
			
		||||
        "out vec2 o_TextCoord;\n"
 | 
			
		||||
        "void main() {\n"
 | 
			
		||||
          "gl_Position = u_Projection * u_View * u_Model * vec4(aPos, 1.0);\n"
 | 
			
		||||
          "o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
 | 
			
		||||
        "}"
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
@@ -37,8 +40,14 @@ void SimpleTexturedShader::getStages(
 | 
			
		||||
        "in vec2 o_TextCoord;\n"
 | 
			
		||||
        "out vec4 o_Color;\n"
 | 
			
		||||
        "uniform vec4 u_Color;\n"
 | 
			
		||||
        "uniform bool u_HasTexture;\n"
 | 
			
		||||
        "uniform sampler2D u_Texture;\n"
 | 
			
		||||
        "void main() {\n"
 | 
			
		||||
          "o_Color = u_Color;"
 | 
			
		||||
          "if(u_HasTexture) {\n"
 | 
			
		||||
            "o_Color = texture(u_Texture, o_TextCoord) * u_Color;\n"
 | 
			
		||||
          "} else {\n"
 | 
			
		||||
            "o_Color = u_Color;"
 | 
			
		||||
          "}\n"
 | 
			
		||||
        "}\n"
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
@@ -75,4 +84,16 @@ void SimpleTexturedShader::getStages(
 | 
			
		||||
    &rel->color,
 | 
			
		||||
    ShaderParameterType::COLOR
 | 
			
		||||
  ));
 | 
			
		||||
 | 
			
		||||
  parameters.push_back(ShaderOpenGLParameter(
 | 
			
		||||
    "u_HasTexture",
 | 
			
		||||
    &rel->hasTexture,
 | 
			
		||||
    ShaderParameterType::BOOLEAN
 | 
			
		||||
  ));
 | 
			
		||||
 | 
			
		||||
  parameters.push_back(ShaderOpenGLParameter(
 | 
			
		||||
    "u_Texture",
 | 
			
		||||
    &rel->texture,
 | 
			
		||||
    ShaderParameterType::TEXTURE
 | 
			
		||||
  ));
 | 
			
		||||
}
 | 
			
		||||
@@ -12,6 +12,8 @@ namespace Dawn {
 | 
			
		||||
    glm::mat4 view;
 | 
			
		||||
    glm::mat4 model;
 | 
			
		||||
    struct Color color = COLOR_WHITE;
 | 
			
		||||
    bool hasTexture = false;
 | 
			
		||||
    shadertexturebinding_t texture = 0;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  class SimpleTexturedShader : public Shader<SimpleTexturedShaderData> {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user