microsoft / angle

ANGLE: OpenGL ES to DirectX translation
Other
615 stars 166 forks source link

Windows phone point rendering #15

Closed amerkoleci closed 9 years ago

amerkoleci commented 10 years ago

Angle from google uses geometry shaders for rendering points on GPU, Windows Phone 8.1 supports feature level 3.1 which does not support geomtry shaders, how this will be handled?

coopp commented 10 years ago

We have this item on our list of things to investigate. You are correct that Windows Phone 8.1 with limited feature level settings does not support geometry shaders. We will be looking into some solutions for that in the next coming months. It is a challenging problem, but we plan on addressing it in some way.

benaadams commented 10 years ago

Does it not support Direct3D 9 Point Sprites? http://msdn.microsoft.com/en-gb/library/windows/desktop/bb147281(v=vs.85).aspx

austinkinross commented 10 years ago

Windows Store apps (for both Windows 8.1 and Windows Phone 8.1) must use Direct3D 11.

benaadams commented 10 years ago

Ah didn't know Direct3D 11 had dropped them; suppose there are a few ways though: http://blogs.msdn.com/b/ivanne/archive/2012/01/04/multiple-ways-to-render-point-sprites-in-dx11.aspx

coopp commented 10 years ago

Yes. That blog post covers them pretty well.

stammen commented 10 years ago

Could we support a gl_PointSize of 1 without a compute shader for DirectX level 9_3?

amerkoleci commented 9 years ago

Point rendering has landed, would be possible to merge?

https://chromium.googlesource.com/angle/angle/+/e6664f06415d498896e0c94c6e88e4be5fd847cb

I saw angle from google has all winrt code, does this make sense to exists?

coopp commented 9 years ago

PointSprites for FL9_3 from Google's master branch will be merged back into future-dev very soon. We are working on managing that merge this week and next week.

austinkinross commented 9 years ago

We merged Google's master branch into future-dev today, so point sprites are now available in future-dev.

Bastl34 commented 9 years ago

It seems to be a little bit buggy. Its only working if the shader attribute position of the vertices is not at 0. It the position is at 0 -> all vertices are having 0,0,0 as position

Running this on the Windows Phone Emulator: Everything is fine if the vertex-attribute is not at position 0. This is a sample of a campfire smoke: Ok

Running this on a Windows Phone 8.1 device (Lumia 1020): It looks like this Ok

Here is a shader example:

attribute vec3 aDummy;
attribute vec3 aPosition; //if vertex-shader-pos is at pos=0 -> all vertices are at 0,0,0
attribute vec4 aColor;

...

void main()
{
    vec3 test = aDummy;

    gl_Position = uMVP * vec4(aPosition,1.0);

    gl_PointSize = ...
}
coopp commented 9 years ago

Thanks for reporting this issue. I will investigate the 0 position bug this week and see if I can get a better understanding of what is going on here.

coopp commented 9 years ago

I cannot repro your issue. I authored a shader that forced the position to 0,0,0 and the pointsprite rendered correctly. The difference in my repro is I didn't use a MVP to adjust the position of the sprite.

void main() { gl_Position = vec4(0, 0, 0, 1); gl_PointSize = 40.0; }

If you can provide a sample that demonstrates your issue, I would be happy to look further into this.

Bastl34 commented 9 years ago

It seems that something is getting wrong with the attributes. If I set all values (position, color) in the shader, everything looks fine. But if I use attributes (for position, color, ...) something is getting wrong. (with VBO or without VBO does not matter)

with position/color in shader: without attributes

with aColor(black) from C++-source: with attributes #1 with attributes #1

Here are my sample shaders:

attribute vec3 aDummy;
attribute vec3 aPosition;
attribute vec4 aColor;

varying vec4 vColor;

void main()
{
    //to prevent that aDummy and aPosition are optimized out
    vec3 test = aDummy;
    vec3 pos = aPosition;

    vColor = vec4(0.8,0.8,0.8,0.8);
    //vColor = aColor; //using this line: the rainbow effect appears

    gl_Position = vec4(0.0,0.0,0.0,1.0);
    gl_PointSize = 100.0;
}
precision highp float;

varying vec4 vColor;
uniform sampler2D uTexDiffuse;

void main()
{
    gl_FragColor = vColor * texture2D( uTexDiffuse, gl_PointCoord);
}

drawing:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);

glVertexAttribPointer(aPosition, 3, GL_FLOAT, GL_FALSE, 0, &obj.vertices[0]);
glEnableVertexAttribArray(aPosition);               
glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, 0, &obj.colors[0]);
glEnableVertexAttribArray(aColor);

glDepthMask(GL_FALSE);
glDrawArrays(GL_POINTS, 0, (unsigned int)obj.vertices.size());
glDepthMask(GL_TRUE);
coopp commented 9 years ago

I modified the ANGLE Win32 ParticleSystem sample to match your example and I am not seeing the same results. The vColor varying is being properly set and the pointsprite is tented the correct color without the rainbow effect.

Could there be an additional detail that I am missing? Below are the modifications to the ParticleSystemSample I made to try and repro your issue.

class ParticleSystemSample : public SampleApplication
{
  public:
      ParticleSystemSample::ParticleSystemSample()
        : SampleApplication("ParticleSystem", 1280, 720)
    {
    }

    virtual bool initialize()
    {
        const std::string vs = SHADER_SOURCE
        (
            attribute vec3 aDummy;
            attribute vec3 aPosition;
            attribute vec4 aColor;

            varying vec4 vColor;

            void main()
            {
                //to prevent that aDummy and aPosition are optimized out
                vec3 test = aDummy;
                vec3 pos = aPosition;

                //vColor = vec4(0.8, 0.8, 0.8, 0.8);
                vColor = aColor; //using this line: the rainbow effect appears

                gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
                gl_PointSize = 100.0;
            }
        );

        const std::string fs = SHADER_SOURCE
        (
            precision highp float;
            varying vec4 vColor;
            uniform sampler2D uTexDiffuse;
            void main()
            {
                gl_FragColor = vColor * texture2D(uTexDiffuse, gl_PointCoord);
            }
        );

        mProgram = CompileProgram(vs, fs);
        if (!mProgram)
        {
            return false;
        }

        vertices.push_back(Vector3(0, 0, 0));
        colors.push_back(Vector4(1, 0, 0, 1));

        // Get the attribute locations
        aDummy = glGetAttribLocation(mProgram, "aDummy");
        aPosition = glGetAttribLocation(mProgram, "aPosition");
        aColor = glGetAttribLocation(mProgram, "aColor");
        vColor = glGetAttribLocation(mProgram, "vColor");

        uTexDiffuse = glGetUniformLocation(mProgram, "uTexDiffuse");

        glClearColor(0.45f, 0.58f, 0.73f, 0.0f);

        TGAImage img;
        if (!LoadTGAImageFromFile(GetExecutableDirectory() + "/smoke.tga", &img))
        {
            return false;
        }
        mTextureID = LoadTextureFromTGAImage(img);
        if (!mTextureID)
        {
            return false;
        }

        return true;
    }

    virtual void destroy()
    {
        glDeleteProgram(mProgram);
    }

    virtual void step(float dt, double totalTime)
    {
        // Use the program object
        glUseProgram(mProgram);
    }

    virtual void draw()
    {
        // Set the viewport
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

        // Clear the color buffer
        glClear(GL_COLOR_BUFFER_BIT);

        // Use the program object
        glUseProgram(mProgram);

        // Bind the texture
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, mTextureID);

        glVertexAttribPointer(aPosition, 3, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
        glEnableVertexAttribArray(aPosition);
        glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, 0, &colors[0]);
        glEnableVertexAttribArray(aColor);

        glDepthMask(GL_FALSE);
        glDrawArrays(GL_POINTS, 0, (unsigned int)vertices.size());
        glDepthMask(GL_TRUE);
    }

  private:
    // Handle to a program object
    GLuint mProgram;

    // Attribute locations
    GLint aDummy;
    GLint aPosition;
    GLint aColor;
    GLint uTexDiffuse;

    // Varying location
    GLint vColor;

    // Texture handle
    GLuint mTextureID;

    std::vector<Vector3> vertices;
    std::vector<Vector4> colors;
};
benaadams commented 9 years ago

Do you ever bind data to the attribute attribute vec3 aDummy?

Bastl34 commented 9 years ago

Hi. Thanks for helping me out with this.

I ripped out everything related of my framework and based on your sample I have now the following code: (using the the hello triangle template)

HelloTriangleRenderer.h:

#pragma once

#include "pch.h"

#include <glm/glm.hpp>

namespace RuntimeComponent
{
    class HelloTriangleRenderer
    {
    public:
        HelloTriangleRenderer();
        ~HelloTriangleRenderer();
        void Draw(GLsizei width, GLsizei height);

    private:
        GLuint mProgram;

        // Attribute locations
        GLint aDummy;
        GLint aPosition;
        GLint aColor;
        GLint uTexDiffuse;

        // Varying location
        GLint vColor;

        // Texture handle
        GLuint mTextureID;

        std::vector<glm::vec3> vertices;
        std::vector<glm::vec4> colors;
    };
}

HelloTriangleRenderer.cpp

//            Based on Hello_Triangle.c from
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com

//
// This file is used by the template to render a basic scene using GL.
//

#include "pch.h"
#include "HelloTriangleRenderer.h"

// These are used by the shader compilation methods.
#include <vector>
#include <iostream>
#include <fstream>

using namespace Platform;

using namespace RuntimeComponent;

#define STRING(s) #s

GLuint CompileShader(GLenum type, const std::string &source)
{
    GLuint shader = glCreateShader(type);

    const char *sourceArray[1] = { source.c_str() };
    glShaderSource(shader, 1, sourceArray, NULL);
    glCompileShader(shader);

    GLint compileResult;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);

    if (compileResult == 0)
    {
        GLint infoLogLength;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);

        std::vector<GLchar> infoLog(infoLogLength);
        glGetShaderInfoLog(shader, (GLsizei)infoLog.size(), NULL, infoLog.data());

        std::wstring errorMessage = std::wstring(L"Shader compilation failed: ");
        errorMessage += std::wstring(infoLog.begin(), infoLog.end()); 

        throw Exception::CreateException(E_FAIL, ref new Platform::String(errorMessage.c_str()));
    }

    return shader;
}

GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
{
    GLuint program = glCreateProgram();

    if (program == 0)
    {
        throw Exception::CreateException(E_FAIL, L"Program creation failed");
    }

    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);

    if (vs == 0 || fs == 0)
    {
        glDeleteShader(fs);
        glDeleteShader(vs);
        glDeleteProgram(program);
        return 0;
    }

    glAttachShader(program, vs);
    glDeleteShader(vs);

    glAttachShader(program, fs);
    glDeleteShader(fs);

    glLinkProgram(program);

    GLint linkStatus;
    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);

    if (linkStatus == 0)
    {
        GLint infoLogLength;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);

        std::vector<GLchar> infoLog(infoLogLength);
        glGetProgramInfoLog(program, (GLsizei)infoLog.size(), NULL, infoLog.data());

        std::wstring errorMessage = std::wstring(L"Program link failed: ");
        errorMessage += std::wstring(infoLog.begin(), infoLog.end()); 

        throw Exception::CreateException(E_FAIL, ref new Platform::String(errorMessage.c_str()));
    }

    return program;
}

HelloTriangleRenderer::HelloTriangleRenderer() :
    mProgram(0)
{
    // Vertex Shader source
    const std::string vs = STRING
    (
        //attribute vec3 aDummy;
        attribute vec3 aPosition;
        attribute vec4 aColor;

        varying vec4 vColor;

        void main()
        {
            //to prevent that aDummy and aPosition are optimized out
            //vec3 test = aDummy;
            vec3 pos = aPosition;

            //vColor = vec4(0.8, 0.8, 0.8, 0.8);
            vColor = aColor;

            gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
            //gl_Position = vec4(aPosition, 1.0); //using this line will be result in Image #2

            gl_PointSize = 300.0;
        }
    );

    // Fragment Shader source
    const std::string fs = STRING
    (
        precision highp float;
        varying vec4 vColor;
        uniform sampler2D uTexDiffuse;
        void main()
        {
            //gl_FragColor = vColor * texture2D(uTexDiffuse, gl_PointCoord);
            gl_FragColor = vColor;
        }
    );

    // CompileProgram will throw if it fails, so we don't need to check for success.
    mProgram = CompileProgram(vs, fs);

    vertices.push_back(glm::vec3(0, 0, 0));
    colors.push_back(glm::vec4(1, 0, 0, 1));

    // Get the attribute locations
    //aDummy = glGetAttribLocation(mProgram, "aDummy");
    aPosition = glGetAttribLocation(mProgram, "aPosition");
    aColor = glGetAttribLocation(mProgram, "aColor");
    vColor = glGetAttribLocation(mProgram, "vColor");

    uTexDiffuse = glGetUniformLocation(mProgram, "uTexDiffuse");

    glClearColor(0.45f, 0.58f, 0.73f, 0.0f);
}

HelloTriangleRenderer::~HelloTriangleRenderer()
{
    if (mProgram != 0)
    {
        glDeleteProgram(mProgram);
        mProgram = 0;
    }
}

// Draws a basic triangle
void HelloTriangleRenderer::Draw(GLsizei width, GLsizei height)
{
    // Set the viewport
    glViewport(0, 0, width, height);

    // Clear the color buffer
    glClear(GL_COLOR_BUFFER_BIT);

    // Use the program object
    glUseProgram(mProgram);

    // Bind the texture
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mTextureID);

    glVertexAttribPointer(aPosition, 3, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
    glEnableVertexAttribArray(aPosition);
    glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, 0, &colors[0]);
    glEnableVertexAttribArray(aColor);

    glDepthMask(GL_FALSE);
    glDrawArrays(GL_POINTS, 0, (unsigned int) vertices.size());
    glDepthMask(GL_TRUE);
}

Resulting Images:

Image # 1 (With position set in shader): without attributes

Image # 2 (With position from source - see shader source and uncomment gl_Position = vec4(aPosition, 1.0);) without attributes

Things I have checked:

Note: This only happens on a device. Not with the emulator

benaadams commented 9 years ago

vColor is a varying that shouldn't be referenced out side of the shaders rather than an attribute?

vColor = glGetAttribLocation(mProgram, "vColor");
Bastl34 commented 9 years ago

You are right. But if I remove this line the output does not change

austinkinross commented 9 years ago

Thank you Bastl34, that's a wonderful repro. I can confirm that I see the same behavior as you on a Lumia 920, but I see the correct behavior on a Lumia 630 and in the Windows Phone Emulator.

We'll continue to investigate this problem and hopefully find a solution. If this issue is blocking you in the meantime then I suggest continuing development in the Windows Phone Emulator, or on a retail phone which shipped with Windows Phone 8.1 on it (such as a Lumia 630 or 530).

Thanks again, Austin

austinkinross commented 9 years ago

This should be fixed in the latest version of ms-master. Thanks again for the repro steps!