Homebrew Segfault when using C3D_DrawArrays()

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
Hi,

I am currently trying to draw a rectangle using Citro3D (I do not want to use some library like sf2d or pp2d) but when I call `C3D_DrawArrays()`, I get a segmentation fault. When I remove this line, the program runs fine, it just doesn't render anything (obviously).

Here is the code where it crashes:

Code:
        m3d::Color color(0, 0, 0, 255);

        m3d::Vertex* vertices = new Vertex[4];

        if (vertices == nullptr) return;

        vertices[0].position = (m3d::Vector3f){(float) 10,                       (float) 20,   0.5f};
        vertices[1].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20,   0.5f};
        vertices[2].position = (m3d::Vector3f){(float) 10,                       (float) 20 + m_height, 0.5f};
        vertices[3].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20 + m_height, 0.5f};

        vertices[0].color = color.getRgba8();
        vertices[1].color = vertices[0].color;
        vertices[2].color = vertices[0].color;
        vertices[3].color = vertices[0].color;

        C3D_TexEnv* env = C3D_GetTexEnv(0);
        C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
        C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
        C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);

        C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
        AttrInfo_Init(attrInfo);
        AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
        AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);

        C3D_BufInfo* bufInfo = C3D_GetBufInfo();
        BufInfo_Init(bufInfo);
        BufInfo_Add(bufInfo, &vertices, sizeof(m3d::Vertex), 2, 0x10);
        C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);

The code I use to start the frame looks like this:
Code:
        C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
        C3D_FrameDrawOn(m_targetBottom->getRenderTarget());

Does anybody know what I'm doing wrong?

~ StuntHacks
 

Essometer

Needs data
Member
Joined
Oct 22, 2010
Messages
732
Trophies
1
Age
32
Location
Bielefeld
Website
none.de
XP
3,557
Country
Germany
I am not an expert in any way so this is just a guess, but try to replace
Code:
BufInfo_Add(bufInfo, &vertices, sizeof(m3d::Vertex), 2, 0x10);
with
Code:
BufInfo_Add(bufInfo, &vertices, sizeof(vertices), 2, 0x10);

I have no experience with Citro3D, but it looks similar to openGl. Are you sure that the coordinate for your rectangle uses Non Normalized Coordinates?

One last thing, I think the argument behind the size is the number of vertices, so it should be 4 instead of 2? Like I said, just a guess.
 
Last edited by Essometer,

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
I am not an expert in any way so this is just a guess, but try to replace
Code:
BufInfo_Add(bufInfo, &vertices, sizeof(m3d::Vertex), 2, 0x10);
with
Code:
BufInfo_Add(bufInfo, &vertices, sizeof(vertices), 2, 0x10);

I have no experience with Citro3D, but it looks similar to openGl. Are you sure that the coordinate for your rectangle uses Non Normalized Coordinates?

One last thing, I think the argument behind the size is the number of vertices, so it should be 4 instead of 2? Like I said, just a guess.

I tried both things, even in different combinations, nothing worked sadly...

But what exactly do you mean by Non Normalized Coordinates? Sorry if this is a noob question, I'm kinda new to Citro3D/Graphical rendering of that kind.
 

Essometer

Needs data
Member
Joined
Oct 22, 2010
Messages
732
Trophies
1
Age
32
Location
Bielefeld
Website
none.de
XP
3,557
Country
Germany
In OpenGL you have a Viewport which is basically the window where thing can be rendered on screen. The
Viewport uses a 3D coordinate system where 0,0,0 is in the middle of the window and the axis go from 1 to -1.

Normalized Coordinate mean that the coords you use to specify the point on the screen need to be between 1 and -1.

Not sure if Citro works this way thou. Also I don't think this would produce a Segfault.

EDIT: Just looked at the programm example, they use Non Normalized Coordinate as well, probably because the Viewport is
always the 3DS Display and has always a size of the screen resolution.
 
Last edited by Essometer,

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
Hi,

I am currently trying to draw a rectangle using Citro3D (I do not want to use some library like sf2d or pp2d) but when I call `C3D_DrawArrays()`, I get a segmentation fault. When I remove this line, the program runs fine, it just doesn't render anything (obviously).

Here is the code where it crashes:

Code:
        m3d::Color color(0, 0, 0, 255);

        m3d::Vertex* vertices = new Vertex[4];

        if (vertices == nullptr) return;

        vertices[0].position = (m3d::Vector3f){(float) 10,                       (float) 20,   0.5f};
        vertices[1].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20,   0.5f};
        vertices[2].position = (m3d::Vector3f){(float) 10,                       (float) 20 + m_height, 0.5f};
        vertices[3].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20 + m_height, 0.5f};

        vertices[0].color = color.getRgba8();
        vertices[1].color = vertices[0].color;
        vertices[2].color = vertices[0].color;
        vertices[3].color = vertices[0].color;

        C3D_TexEnv* env = C3D_GetTexEnv(0);
        C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
        C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
        C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);

        C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
        AttrInfo_Init(attrInfo);
        AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
        AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);

        C3D_BufInfo* bufInfo = C3D_GetBufInfo();
        BufInfo_Init(bufInfo);
        BufInfo_Add(bufInfo, &vertices, sizeof(m3d::Vertex), 2, 0x10);
        C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);

The code I use to start the frame looks like this:
Code:
        C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
        C3D_FrameDrawOn(m_targetBottom->getRenderTarget());

Does anybody know what I'm doing wrong?

~ StuntHacks
Vbo data needs to be in linear (or vram, but linear is easier). You need to use linearAlloc instead new/malloc.
https://github.com/devkitPro/3ds-examples/blob/master/graphics/gpu/simple_tri/source/main.c
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
In OpenGL you have a Viewport which is basically the window where thing can be rendered on screen. The
Viewport uses a 3D coordinate system where 0,0,0 is in the middle of the window and the axis go from 1 to -1.

Normalized Coordinate mean that the coords you use to specify the point on the screen need to be between 1 and -1.

Not sure if Citro works this way thou. Also I don't think this would produce a Segfault.

EDIT: Just looked at the programm example, they use Non Normalized Coordinate as well, probably because the Viewport is
always the 3DS Display and has always a size of the screen resolution.

I checked, and the coordinates are fine. I now even tried to hardcode them, it still doesn't work... There is still the possibility of immediate rendering mode but that completely ruins running the app in citra.

--------------------- MERGED ---------------------------

Vbo data needs to be in linear (or vram, but linear is easier). You need to use linearAlloc instead new/malloc.
https://github.com/devkitPro/3ds-examples/blob/master/graphics/gpu/simple_tri/source/main.c
Okay so I tried doing it like that now:
Code:
m3d::Vertex* vertices = linearAlloc(4 * sizeof(m3d::Vertex));
And now I am getting an `invalid conversion from 'void*' to 'm3d::Vertex*'` error. I am probably just missing something very simple but I really don't get what I'm doing wrong.
 

Essometer

Needs data
Member
Joined
Oct 22, 2010
Messages
732
Trophies
1
Age
32
Location
Bielefeld
Website
none.de
XP
3,557
Country
Germany
Code:
linearAlloc
returns a void pointer which you can't assign to a vertex pointer. In the example
they copy the vertex data with
Code:
memcopy
to the allocated memory.
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
Code:
linearAlloc
returns a void pointer which you can't assign to a vertex pointer. In the example
they copy the vertex data with
Code:
memcopy
to the allocated memory.
I noticed that as well, probably should have posted that. However, now fixed it to:
Code:
m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(4 * sizeof(m3d::Vertex));
And yet it still crashes...
 

TarableCode

Well-Known Member
Member
Joined
Mar 2, 2016
Messages
184
Trophies
0
Age
37
XP
319
Country
Canada
In Bufinfo_Add you're passing a pointer to a pointer, try:
Code:
BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
 
  • Like
Reactions: Coto

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
In Bufinfo_Add you're passing a pointer to a pointer, try:
Code:
BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
I tried that, it still crashes.

My current code is the following:
Code:
        m3d::Color color(255, 0, 0, 255);

        m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(4 * sizeof(m3d::Vertex));

        if (vertices == nullptr) return;

        vertices[0].position = (m3d::Vector3f){(float) 10,                       (float) 20,   0.5f};
        vertices[1].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20,   0.5f};
        vertices[2].position = (m3d::Vector3f){(float) 10,                       (float) 20 + m_height, 0.5f};
        vertices[3].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20 + m_height, 0.5f};

        vertices[0].color = color.getRgba8();
        vertices[1].color = vertices[0].color;
        vertices[2].color = vertices[0].color;
        vertices[3].color = vertices[0].color;

        C3D_TexEnv* env = C3D_GetTexEnv(0);
        C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
        C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
        C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);

        C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
        AttrInfo_Init(attrInfo);
        AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
        AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);

        C3D_BufInfo* bufInfo = C3D_GetBufInfo();
        BufInfo_Init(bufInfo);
        BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
        C3D_SetBufInfo(bufInfo);
        C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 3);
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
It's been a while since I've done any C3D stuff but you can try getting rid of BufInfo_Init and C3D_SetBufInfo.
If it helps any here is what I did for that kind of thing: https://github.com/TaraHoleInIt/minivmac-3ds/blob/master/src/3DSGLU.c#L740
Well, if I get rid of BufInfo_Init, citra prints a `unknown GetPointer` error. And regardless how I try it, it crashes again and again, each time with a segfault.

On a sidenote, thanks for your patient help everyone :)
 

TarableCode

Well-Known Member
Member
Joined
Mar 2, 2016
Messages
184
Trophies
0
Age
37
XP
319
Country
Canada
Oh crap sorry, I had BufInfo_Init in my own code and just completely missed it.
Perhaps you could paste your whole code, it might help to get an idea if the problem lies elsewhere.

Does it run on hardware?
It might just be citra being ornery, often times I'd run into that with code that worked on hardware but barfed in an emulator.
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
Oh crap sorry, I had BufInfo_Init in my own code and just completely missed it.
Perhaps you could paste your whole code, it might help to get an idea if the problem lies elsewhere.

Does it run on hardware?
It might just be citra being ornery, often times I'd run into that with code that worked on hardware but barfed in an emulator.

I just tested it on real hardware. It didn't crash but it looked... weird...
photo_2017-09-13_15-4s4sk0.jpg

Okay so now the code part:
The basic of how I am trying to render the rectangle is this: I have a m3d::Screen-object, which renders the screen, and a m3d::Rectangle object, which is a child of the abstract class m3d::Drawable and draws only the rectangle.

Here is the relevant code of the Screen:
Code:
/**
 * @file screen.hpp
 * @brief The master class for drawing on screens
 */
#pragma once
#include <vector>
#include <map>
#include <cstring>
#include <3ds.h>
#include <citro3d.h>
#include "./renderTarget.hpp"
#include "./drawable.hpp"

/**
 * @brief The general m3d-namespace
 */
namespace m3d {
    /**
     * @brief Defines the screen targets (top/bottom)
     */
    enum ScreenTarget {
        SCREEN_TOP,        ///< Top screen
        SCREEN_BOTTOM    ///< Bottom/touch screen
    };

    /**
     * @brief Defines the two sides in stereoscopic 3D mode
     */
    enum Stereo3dSide {
        SIDE_LEFT = 0, ///< Left side
        SIDE_RIGHT = 1 ///< Right side
    };

    /**
     * @brief The class used for rendering stuff on a screen
     */
    class Screen {
    public:
        /**
         * @brief Initializes the m3d::Screen object
         * @param t_enable3d Whether to enable stereoscopic 3D by default
         */
        Screen(bool t_enable3d = false);

        /**
         * @brief Destructs the screen object
         */
        ~Screen();

        /**
         * @brief Enables or disables stereoscopic 3D
         * @param t_enabled Whether to enable or disable it
         */
        void set3d(bool t_enabled);

        /**
         * @brief Force-clears the screen by resetting all framebuffers of the screen
         */
        void forceClear();

        /**
         * @brief Clears the screen
         */
        void clear();

        /**
         * Draws something on the top screen
         * @param t_object The object that should be drawn
         */
        void drawTop(m3d::Drawable& t_object, int t_layer = 0);

        /**
         * Draws something on the bottom screen
         * @param t_object The object that should be drawn
         */
        void drawBottom(m3d::Drawable& t_object, int t_layer = 0);

        /**
         * @brief Renders the current screen
         */
        void render();

        /**
         * @brief Returns the width of the screen
         * @param t_target The target screen
         * @return The width of the screen in pixels
         */
        int getScreenWidth(m3d::ScreenTarget t_target);

        /**
         * @brief Returns the height of the screen
         * @return The height of the screen in pixels
         */
        int getScreenHeight();

    private:
        /* data */
        m3d::RenderTarget *m_targetTopLeft, *m_targetTopRight, *m_targetBottom;
        std::map<int, std::vector<m3d::Drawable*>> m_drawStackTop, m_drawStackBottom;
        bool m_3dEnabled;

    };
} /* m3d */
Code:
#include "graphics/screen.hpp"

namespace m3d {
    Screen::Screen(bool t_enable3d) {
        gfxInitDefault();
        gfxSet3D(t_enable3d);
        m_3dEnabled = t_enable3d;
        C3D_Init(0x80000 * 8);

        m_targetTopLeft     = new m3d::RenderTarget(400, 240);
        m_targetTopRight     = new m3d::RenderTarget(400, 240);
        m_targetBottom         = new m3d::RenderTarget(320, 240);
        C3D_RenderTargetSetOutput(m_targetTopLeft->getRenderTarget(),  GFX_TOP,    GFX_LEFT,  0x1000);
        C3D_RenderTargetSetOutput(m_targetTopRight->getRenderTarget(), GFX_TOP,    GFX_RIGHT, 0x1000);
        C3D_RenderTargetSetOutput(m_targetBottom->getRenderTarget(), GFX_BOTTOM, GFX_LEFT, 0x1000);
    }

    Screen::~Screen() {
        C3D_Fini();
        gfxExit();
    }

    void Screen::set3d(bool t_enabled) {
        gfxSet3D(t_enabled);
        m_3dEnabled = t_enabled;
    }

    void Screen::forceClear() {
            u8* leftFrameBuffer;
            u8* rightFrameBuffer;
            u8* bottomFrameBuffer;
            leftFrameBuffer = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
            rightFrameBuffer = gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL);
            bottomFrameBuffer = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
            memset(leftFrameBuffer, 0, 400 * 240 * 3);
            memset(rightFrameBuffer, 0, 400 * 240 * 3);
            memset(bottomFrameBuffer, 0, 320 * 240 * 3);
    }

    void Screen::drawTop(m3d::Drawable& t_object, int t_layer) {
        if(m_drawStackTop.count(t_layer) > 0) {
            m_drawStackTop[t_layer].push_back(&t_object);
        } else {
            std::vector<m3d::Drawable*> newStack;
            newStack.push_back(&t_object);
            m_drawStackTop.insert(std::make_pair(t_layer, newStack));
        }
    }

    void Screen::drawBottom(m3d::Drawable& t_object, int t_layer) {
        if(m_drawStackBottom.count(t_layer) > 0) {
            m_drawStackBottom[t_layer].push_back(&t_object);
        } else {
            std::vector<m3d::Drawable*> newStack;
            newStack.push_back(&t_object);
            m_drawStackBottom.insert(std::make_pair(t_layer, newStack));
        }
    }

    void Screen::render() {
        C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
        C3D_FrameDrawOn(m_targetBottom->getRenderTarget());
        C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, 0, m_targetBottom->getProjectionMatrix());

        for(auto const &entry : m_drawStackBottom) {
            for (auto &drawable : entry.second) {
                drawable->draw(m3d::SIDE_LEFT);
            }
        }

        C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
        C3D_FrameDrawOn(m_targetTopLeft->getRenderTarget());
        C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, 0, m_targetTopLeft->getProjectionMatrix());

        for(auto const &entry : m_drawStackTop) {
            for (auto &drawable : entry.second) {
                drawable->draw(m3d::SIDE_LEFT);
            }
        }

        C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
        C3D_FrameDrawOn(m_targetTopRight->getRenderTarget());
        C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, 0, m_targetTopRight->getProjectionMatrix());

        for(auto const &entry : m_drawStackTop) {
            for (auto const &drawable : entry.second) {
                drawable->draw(m3d::SIDE_RIGHT);
            }
        }

        C3D_FrameEnd(0);
        m_drawStackTop.clear();
        m_drawStackBottom.clear();
    }

    int Screen::getScreenWidth(m3d::ScreenTarget t_target) {
        return (t_target == SCREEN_TOP ? 400 : 320);
    }

    int Screen::getScreenHeight() {
        return 240;
    }
} /* m3d */
Code:
#pragma once
#include "graphics/drawable.hpp"
#include "graphics/color.hpp"

namespace m3d {
    class Rectangle: public m3d::Drawable {
    public:
        Rectangle(int t_width, int t_height);

        void draw(int t_side);

    private:
        /* data */
        int m_width, m_height;

    };
} /* m3d */
Code:
#include "graphics/drawables/rectangle.hpp"
#include "graphics/vertex.hpp"
#include <vector>

namespace m3d {
    Rectangle::Rectangle(int t_width, int t_height) {
        m_width = t_width;
        m_height = t_height;
    }

    void Rectangle::draw(int t_side) {
        m3d::Color color(255, 0, 0, 255);

        m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(4 * sizeof(m3d::Vertex));

        if (vertices == nullptr) return;

        vertices[0].position = (m3d::Vector3f){(float) 10,                       (float) 20,   0.5f};
        vertices[1].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20,   0.5f};
        vertices[2].position = (m3d::Vector3f){(float) 10,                       (float) 20 + m_height, 0.5f};
        vertices[3].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20 + m_height, 0.5f};

        vertices[0].color = color.getRgba8();
        vertices[1].color = vertices[0].color;
        vertices[2].color = vertices[0].color;
        vertices[3].color = vertices[0].color;

        C3D_TexEnv* env = C3D_GetTexEnv(0);
        C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
        C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
        C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);

        C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
        AttrInfo_Init(attrInfo);
        AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
        AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);
        //
        C3D_BufInfo* bufInfo = C3D_GetBufInfo();
        BufInfo_Init(bufInfo);
        BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
        C3D_SetBufInfo(bufInfo);
        C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 3);
    }
} /* m3d */
Code:
/**
 * @file vertex.hpp
 * @brief Defines the Vertex struct as well as multi-dimensional vectors used for shapes
 */
#pragma once
#include "./color.hpp"

namespace m3d {
    /**
     * @brief Represents a two dimensional float vector
     */
    typedef struct {
        float u;  ///< First component of the vector
        float v;  ///< Second component of the vector
    } Vector2f;

    /**
     * @brief Represents a three dimensional float vector
     */
    typedef struct {
        float x;  ///< First component of the vector
        float y;  ///< Second component of the vector
        float z;  ///< Third component of the vector
    } Vector3f;

    /**
     * @brief Represents a vertex containing its position and its color
     */
    typedef struct {
        Vector3f position;  ///< Position of the vertex
        u32 color;                    ///< Color of the vertex
    } Vertex;
} /* m3d */
And finally, the main.cpp:
Code:
#include <stdio.h>
#include "m3dia.hpp"

int main() {
    gfxInitDefault();

    m3d::Applet app;

    m3d::Screen s;
    m3d::Rectangle rect(20, 30);

    // Main loop
    while (app.isRunning())
    {
        hidScanInput();
        u32 kDown = hidKeysDown();

        if (kDown & KEY_START) app.exit();

        s.drawTop(rect);
        s.render();
    }

    return 0;
}
 

TarableCode

Well-Known Member
Member
Joined
Mar 2, 2016
Messages
184
Trophies
0
Age
37
XP
319
Country
Canada
Maybe my brain is fuzzy and I'm missing it but I don't see where you load and bind a shader program or create the render targets.
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
Maybe my brain is fuzzy and I'm missing it but I don't see where you load and bind a shader program or create the render targets.
I am creating the shader targets in the constructor of the Screen-class, however I am not binding a shader program. Is this required? Most software I have seen online use a file called "shader.shbin" to do that, is that some public file everyone should use or is it just a naming convention and the people have to write it themselves? Because if that's the case, I'm not able to find a file called like that in any repository using that file.

EDIT: Here the code of my RenderTarget class:
Code:
/**
 * @file renderTarget.hpp
 * @brief Defines the RenderTarget class
 */
#pragma once
#include <3ds.h>
#include <citro3d.h>

namespace m3d {
    /**
     * @brief The RenderTarget class, used for drawing stuff onto
     */
    class RenderTarget {
    public:
        /**
         * @brief Creates a render target
         * @param t_width  The width of the target
         * @param t_height The height of the target
         */
        RenderTarget(int t_width, int t_height);

        /**
         * @brief Returns the render target
         * @return The render target
         */
        C3D_RenderTarget* getRenderTarget();

        /**
         * @brief Returns the projection matrix of this render target
         * @return The projection matrix
         */
        C3D_Mtx* getProjectionMatrix();

        /**
         * @brief Returns the width of this render target
         * @return The width of the render target
         */
        int getWidth();

        /**
         * @brief Returns the height of this render target
         * @return The height of the render target
         */
        int getHeight();

    private:
        /* data */
        C3D_RenderTarget* m_target;
        C3D_Mtx m_projection;
        int m_width, m_height;

    };
} /* m3d */
Code:
/**
 * @file renderTarget.hpp
 * @brief Defines the RenderTarget class
 */
#pragma once
#include <3ds.h>
#include <citro3d.h>

namespace m3d {
    /**
     * @brief The RenderTarget class, used for drawing stuff onto
     */
    class RenderTarget {
    public:
        /**
         * @brief Creates a render target
         * @param t_width  The width of the target
         * @param t_height The height of the target
         */
        RenderTarget(int t_width, int t_height);

        /**
         * @brief Returns the render target
         * @return The render target
         */
        C3D_RenderTarget* getRenderTarget();

        /**
         * @brief Returns the projection matrix of this render target
         * @return The projection matrix
         */
        C3D_Mtx* getProjectionMatrix();

        /**
         * @brief Returns the width of this render target
         * @return The width of the render target
         */
        int getWidth();

        /**
         * @brief Returns the height of this render target
         * @return The height of the render target
         */
        int getHeight();

    private:
        /* data */
        C3D_RenderTarget* m_target;
        C3D_Mtx m_projection;
        int m_width, m_height;

    };
} /* m3d */
 
Last edited by StuntHacks,

TarableCode

Well-Known Member
Member
Joined
Mar 2, 2016
Messages
184
Trophies
0
Age
37
XP
319
Country
Canada
If you have a shader source file named "vshader.v.pica" it will be compiled during the build process and be available within your app using an auto generated header file.
A good example might be https://github.com/devkitPro/3ds-examples/tree/master/graphics/gpu/gpusprites to take a look at since that's where I started from and it helped me quite a bit.

Afaik you do need to bind a shader program for anything 3d related to work.
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
If you have a shader source file named "vshader.v.pica" it will be compiled during the build process and be available within your app using an auto generated header file.
A good example might be https://github.com/devkitPro/3ds-examples/tree/master/graphics/gpu/gpusprites to take a look at since that's where I started from and it helped me quite a bit.

Afaik you do need to bind a shader program for anything 3d related to work.
Thank you so much, it doesn't crash anymore. However, in citra it doesn't render anything at all and on my 3DS it looks like, well, this (I hardcoded the clear color to white since the last code change, so don't be confused by that):
photo_2017-09-13_16-48qs37.jpg
Those strange line do in fact have the color I hardcoded into the rectangle class, however it doesn't look like a rectangle to me. I'm probably missing something but I don't really get what i'm doing wrong.
 

StuntHacks

Well-Known Member
OP
Newcomer
Joined
Jan 19, 2017
Messages
46
Trophies
0
Age
24
Location
Vienna
XP
227
Country
Austria
A rectangle would need to be made of two triangles with 6 vertices.
Perhaps this might help: https://github.com/TaraHoleInIt/minivmac-3ds/blob/master/src/3DSGLU.c#L585
Please forgive me if I'm just dumb right now but I just don't understand what's going on. Now, I decided I'd just draw a single triangle on the screen. But instead of that, nothing gets drawn, neither on hardware nor in citra.

Here is the current drawing code:
Code:
        m3d::Color color(0, 255, 0, 255);

        m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(3 * sizeof(m3d::Vertex));

        if (vertices == nullptr) return;

        vertices[0].position = (m3d::Vector3f){(float) -0.7, (float) -0.7, 0.5f};
        vertices[1].position = (m3d::Vector3f){(float) -0.7, (float) 0.7, 0.5f};
        vertices[2].position = (m3d::Vector3f){(float) 0.7, (float) 0.5, 0.5f};

        vertices[0].color = color.getRgba8();
        vertices[1].color = vertices[0].color;
        vertices[2].color = vertices[0].color;

        C3D_TexEnv* env = C3D_GetTexEnv(0);
        C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
        C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
        C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);

        C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
        AttrInfo_Init(attrInfo);
        AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
        AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);

        C3D_BufInfo* bufInfo = C3D_GetBufInfo();
        BufInfo_Init(bufInfo);
        BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
        C3D_DrawArrays(GPU_TRIANGLES, 0, 3);
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    K3Nv2 @ K3Nv2: Did you pee in the water