dengfan
Topic Author
Posts: 16
Joined: 19 Nov 2023, 10:32

scrollviewer content overflow flashing bug

16 Dec 2023, 12:25

bug code 2023-12-16 191727.png
bug code 2.png
and if the text of the textblock in scrollviewer is short, it will be very ok.

how to fix it?
 
User avatar
jsantos
Site Admin
Posts: 3925
Joined: 20 Jan 2012, 17:18
Contact:

Re: scrollviewer content overflow flashing bug

18 Dec 2023, 11:29

This seems to be an integration issue on your side. Make sure the offscreen phase is rendered before binding the main framebuffer, just have a look at our IntegrationGLUT sample.
 
User avatar
sfernandez
Site Admin
Posts: 2997
Joined: 22 Dec 2011, 19:20

Re: scrollviewer content overflow flashing bug

18 Dec 2023, 18:40

And also make sure you are using a render target with DepthStencil, because the ScrollViewer uses stencil when it needs to clip its contents to the visible viewport.
 
dengfan
Topic Author
Posts: 16
Joined: 19 Nov 2023, 10:32

Re: scrollviewer content overflow flashing bug

19 Dec 2023, 06:00

And also make sure you are using a render target with DepthStencil, because the ScrollViewer uses stencil when it needs to clip its contents to the visible viewport.
This seems to be an integration issue on your side. Make sure the offscreen phase is rendered before binding the main framebuffer, just have a look at our IntegrationGLUT sample.
Thank you for your answer, I've tried your methods, but it also didn't work.
But when I used the "LayeredUI" approach to load the xaml include scrollviewer, the bug didn't show up and it worked very well.
 
User avatar
jsantos
Site Admin
Posts: 3925
Joined: 20 Jan 2012, 17:18
Contact:

Re: scrollviewer content overflow flashing bug

19 Dec 2023, 19:21

Are you able to reproduce this problem in the IntegrationGLUT sample? If so, please let us know the patches we should apply to see this bug.
 
dengfan
Topic Author
Posts: 16
Joined: 19 Nov 2023, 10:32

Re: scrollviewer content overflow flashing bug

20 Dec 2023, 08:08

I am very sorry, i can not draw a triangle before draw noesisgui in IntegrationGLUT sample,
so i can't reproduce the bug, draw a triangle too hard in glut, i tried 3 hours without success. :(
 
dengfan
Topic Author
Posts: 16
Joined: 19 Nov 2023, 10:32

Re: scrollviewer content overflow flashing bug

20 Dec 2023, 08:11

Are you able to reproduce this problem in the IntegrationGLUT sample? If so, please let us know the patches we should apply to see this bug.
You just draw a triangle before draw noesisgui(xaml, scrollviewer with long textblock), the problem will be reproduce.
 
dengfan
Topic Author
Posts: 16
Joined: 19 Nov 2023, 10:32

Re: scrollviewer content overflow flashing bug

20 Dec 2023, 08:27

This is the code:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <NsGui/IView.h>
#include <NsGui/IRenderer.h>
#include <NsGui/TextBlock.h>
#include <NsGui/Storyboard.h>
#include <NsApp/ThemeProviders.h>
#include <NsGui/FontProperties.h>
#include <NsGui/Grid.h>
#include <NsGui/IntegrationAPI.h>
#include <NsRender/GLFactory.h>
#include <NsRender/GLRenderDeviceApi.h>
#include <NsGui/Uri.h>

#include <iostream>
#include <cstdio>

void cbFramebufferSize(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void myNoesisRender(unsigned int targetFbo);
void myNoesisInit();
void myCreateFramebuffer();
void mySetupGlfw();
void mySetupTriangle();
void myDrawTriangle(unsigned int targetFbo);

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

static Noesis::IView* _view;
static GLFWwindow* pWindow;
unsigned int fbo;
unsigned int triangleVBO, triangleVAO;
unsigned int textColorBuffer;
int numFrames = 0;

float triangleVertices[] = {
	-0.5f, -0.5f, 0.0f,
	 0.5f, -0.5f, 0.0f,
	 0.0f,  0.5f, 0.0f
};
int numTriangleVertices = 3;

const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";

const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{"
"	FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);"
"}\0";

unsigned int shaderProgram;


//====================================================================================
int main()
{
	mySetupGlfw();

	GLenum glew_err = glewInit();
	if (glew_err != GLEW_OK)
	{
		throw std::runtime_error(std::string("Error initializing GLEW, error: ") + (const char*)glewGetErrorString(glew_err));
		return 0;
	}

	glEnable(GL_STENCIL_TEST);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	unsigned int vertexShader;
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);


	unsigned int fragmentShader;
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);

	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);

	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	mySetupTriangle();
	myCreateFramebuffer();

	myNoesisInit();

	while (!glfwWindowShouldClose(pWindow)) {
		processInput(pWindow);

		myDrawTriangle(0);
		myNoesisRender(fbo);

		// Done drawing
		glfwSwapBuffers(pWindow);
		glfwPollEvents();
	}

	_view->GetRenderer()->Shutdown();
	_view->Release();

	glfwTerminate();
	return 0;
}

//----------------------------------------------------------------------------------------
void myNoesisRender(unsigned int targetFramebuffer)
{
	glBindFramebuffer(GL_FRAMEBUFFER, targetFramebuffer);

	int w, h;
	glfwGetFramebufferSize(pWindow, &w, &h);
	glViewport(0, 0, w, h);

	glClearColor(0.3f, 0.3f, 0.0f, 0.0f);
	glClearStencil(0);
	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Update view (layout, animations, ...)
	_view->Update(glfwGetTimerValue() / 1000.0f);

	// Offscreen rendering phase populates textures needed by the on-screen rendering
	_view->GetRenderer()->UpdateRenderTree();
	_view->GetRenderer()->RenderOffscreen();

	// If you are going to render here with your own engine you need to restore the GPU state
	// because noesis changes it. In this case only framebuffer and viewport need to be restored

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	// Rendering is done in the active framebuffer
	_view->GetRenderer()->Render();
}

//--------------------------------------------------------------------------------------
void myNoesisInit() {
	// A logging handler is installed here. You can also install a custom error handler and memory
	// allocator. By default errors are redirected to the logging handler
	Noesis::GUI::SetLogHandler([](const char*, uint32_t, uint32_t level, const char*, const char* msg)
		{
			// [TRACE] [DEBUG] [INFO] [WARNING] [ERROR]
			const char* prefixes[] = { "T", "D", "I", "W", "E" };
			printf("[NOESIS/%s] %s\n", prefixes[level], msg);
		});

	// https://www.noesisengine.com/docs/Gui.Core.Licensing.html
	Noesis::GUI::SetLicense(NS_LICENSE_NAME, NS_LICENSE_KEY);

	// Noesis initialization. This must be the first step before using any NoesisGUI functionality
	Noesis::GUI::Init();

	// Setup theme
	NoesisApp::SetThemeProviders();
	Noesis::GUI::LoadApplicationResources("Theme/NoesisTheme.LightLime.xaml");

	// For simplicity purposes we are not using resource providers in this sample. ParseXaml() is
	// enough if there is no extra XAML dependencies
	Noesis::Ptr<Noesis::Grid> xaml(Noesis::GUI::ParseXaml<Noesis::Grid>(R"(
        <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
              Background="Green"
              HorizontalAlignment="Center"
              VerticalAlignment="Center">
            <ScrollViewer Margin="10"
                          Background="Red"
                          Width="160"
                          Height="100"
                          VerticalScrollBarVisibility="Auto">
                <TextBlock Padding="8 8 20 20"
                           FontSize="16"
                           Width="160"
                           TextWrapping="Wrap"
                           Text="adfkjakfdjka asd fads a dkw wlasa sdasdfasdf asd f asdf asdfdaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaasdf asdf  df asdf afadsf asdf asdf sdf adsf asdf1 11133 444444444445 55." />
            </ScrollViewer>
        </Grid>
    )"));

	// View creation to render and interact with the user interface
	// We transfer the ownership to a global pointer instead of a Ptr<> because there is no way
	// in GLUT to do shutdown and we don't want the Ptr<> to be released at global time
	_view = Noesis::GUI::CreateView(xaml).GiveOwnership();
	_view->SetFlags(Noesis::RenderFlags_PPAA | Noesis::RenderFlags_LCD);
	_view->SetSize(800, 600);
	// Renderer initialization with an OpenGL device
	_view->GetRenderer()->Init(NoesisApp::GLFactory::CreateDevice(false));
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* pWwindow)
{
	if (glfwGetKey(pWwindow, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		glfwSetWindowShouldClose(pWwindow, true);
	}
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void cbFramebufferSize(GLFWwindow* pWnd, int w, int h)
{
	// make sure the viewport matches the new window dimensions; note that width and 
	// height will be significantly larger than specified on retina displays.
	glViewport(0, 0, w, h);
	_view->SetSize(w, h);
}

//---------------------------------------------------------------
void myCreateFramebuffer()
{
	glGenFramebuffers(1, &fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);

	glGenTextures(1, &textColorBuffer);
	glBindTexture(GL_TEXTURE_2D, textColorBuffer);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glBindTexture(GL_TEXTURE_2D, 0);

	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textColorBuffer, 0);

	unsigned int rbo;
	glGenRenderbuffers(1, &rbo);
	glBindRenderbuffer(GL_RENDERBUFFER, rbo);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		printf("Framebuffer is not complete!\n");
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

//----------------------------------------------------------------------
void mySetupGlfw()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE);
	glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);

	pWindow = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Demo", nullptr, nullptr);
	if (pWindow == nullptr) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return;
	}
	glfwSetWindowPos(pWindow, 800, 600);

	glfwMakeContextCurrent(pWindow);
	glfwSetFramebufferSizeCallback(pWindow, cbFramebufferSize);

	//if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
	//	std::cout << "Failed to initialize GLAD" << std::endl;
	//	return;
	//}

	glfwSwapInterval(1);
}

//------------------------------------------------------------------------
void mySetupTriangle() {
	glGenVertexArrays(1, &triangleVAO);
	glGenBuffers(1, &triangleVBO);
	glBindVertexArray(triangleVAO);
	glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
}


//------------------------------------------------------------------------
void myDrawTriangle(unsigned int targetFbo) {
	glBindFramebuffer(GL_FRAMEBUFFER, targetFbo);

	glClearColor(0.1f, 0.3f, 0.3f, 0.0f);
	glClearStencil(0);
	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	glUseProgram(shaderProgram);
	glBindVertexArray(triangleVAO);
	glDisable(GL_DEPTH_TEST);
	glBindTexture(GL_TEXTURE_2D, textColorBuffer);
	glDrawArrays(GL_TRIANGLES, 0, numTriangleVertices);
}
 
User avatar
jsantos
Site Admin
Posts: 3925
Joined: 20 Jan 2012, 17:18
Contact:

Re: scrollviewer content overflow flashing bug

20 Dec 2023, 20:03

Your code is not correct. Please, make sure to follow our tutorials and examples. The correct, per frame steps are:

1. Noesis Update
2. Noesis UpdateRenderTree
3. Noesis RenderOffscreen
4. Bind main framebuffer and set viewport
5. Render your triangle
6. Noesis Render

If you need more complex scenarios, I recommend RenderDoc for capturing the frame and understand what's happening. After invoking RenderOffscreen or Render the GPU state may have changed and you need to restore it (even the active framebuffer and viewport dimensions, RenderOffscreen may change it)
 
dengfan
Topic Author
Posts: 16
Joined: 19 Nov 2023, 10:32

Re: scrollviewer content overflow flashing bug

21 Dec 2023, 05:44

Your code is not correct. Please, make sure to follow our tutorials and examples. The correct, per frame steps are: ...
Thx, I fixed the issue as you said.
The point of the question is:
don't set this line "_view->SetSize(SCR_WIDTH, SCR_HEIGHT);" in NoesisInit().
and set that line in main loop, it will be success.
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <NsGui/IView.h>
#include <NsGui/IRenderer.h>
#include <NsGui/TextBlock.h>
#include <NsApp/ThemeProviders.h>
#include <NsGui/FontProperties.h>
#include <NsGui/Grid.h>
#include <NsGui/IntegrationAPI.h>
#include <NsRender/GLFactory.h>
#include <NsRender/GLRenderDeviceApi.h>
#include <NsGui/Uri.h>

#include <iostream>
#include <cstdio>

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

Noesis::IView* _view;
GLFWwindow* pWindow;
unsigned int triangleVBO, triangleVAO, shaderProgram;

float triangleVertices[] = {
	-0.5f, -0.5f, 0.0f,
	 0.5f, -0.5f, 0.0f,
	 0.0f,  0.5f, 0.0f
};

const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";

const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{"
"	FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);"
"}\0";

void NoesisInit()
{
	// A logging handler is installed here. You can also install a custom error handler and memory
	// allocator. By default errors are redirected to the logging handler
	Noesis::GUI::SetLogHandler([](const char*, uint32_t, uint32_t level, const char*, const char* msg)
		{
			// [TRACE] [DEBUG] [INFO] [WARNING] [ERROR]
			const char* prefixes[] = { "T", "D", "I", "W", "E" };
			printf("[NOESIS/%s] %s\n", prefixes[level], msg);
		});

	// https://www.noesisengine.com/docs/Gui.Core.Licensing.html
	Noesis::GUI::SetLicense(NS_LICENSE_NAME, NS_LICENSE_KEY);

	// Noesis initialization. This must be the first step before using any NoesisGUI functionality
	Noesis::GUI::Init();

	// Setup theme
	NoesisApp::SetThemeProviders();
	Noesis::GUI::LoadApplicationResources("Theme/NoesisTheme.DarkBlue.xaml");

	// For simplicity purposes we are not using resource providers in this sample. ParseXaml() is
	// enough if there is no extra XAML dependencies
	Noesis::Ptr<Noesis::Grid> xaml(Noesis::GUI::ParseXaml<Noesis::Grid>(R"(
        <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
              Background="Green"

              HorizontalAlignment="Center"
              VerticalAlignment="Center" >

<ScrollViewer Margin="10"
                          Background="Red"
                          Width="160"
                          Height="100"
                          VerticalScrollBarVisibility="Auto">
                <TextBlock Padding="8 8 20 20"
                           FontSize="16"
                           Width="160"
                           TextWrapping="Wrap"
                           Text="adfkjakfdjka asd fads a dkw wlasa sdasdfasdf asd f asdf asdfdaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaasdf asdf  df asdf afadsf asdf asdf sdf adsf asdf1 11133 444444444445 55." />
            </ScrollViewer>

        </Grid>
    )"));

	// View creation to render and interact with the user interface
	// We transfer the ownership to a global pointer instead of a Ptr<> because there is no way
	// in GLUT to do shutdown and we don't want the Ptr<> to be released at global time
	_view = Noesis::GUI::CreateView(xaml).GiveOwnership();
	_view->SetFlags(Noesis::RenderFlags_PPAA | Noesis::RenderFlags_LCD);
	
	// Renderer initialization with an OpenGL device
	_view->GetRenderer()->Init(NoesisApp::GLFactory::CreateDevice(false));
}

//====================================================================================
int main()
{
	glfwInit();

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	pWindow = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Demo", nullptr, nullptr);
	if (pWindow == nullptr) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return 0;
	}

	glfwMakeContextCurrent(pWindow);

	glfwSwapInterval(1);

	GLenum glew_err = glewInit();
	if (glew_err != GLEW_OK)
	{
		throw std::runtime_error(std::string("Error initializing GLEW, error: ") + (const char*)glewGetErrorString(glew_err));
		return 0;
	}

	NoesisInit();

	unsigned int vertexShader;
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);

	unsigned int fragmentShader;
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);

	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);

	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	glGenVertexArrays(1, &triangleVAO);
	glGenBuffers(1, &triangleVBO);
	glBindVertexArray(triangleVAO);
	glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	while (!glfwWindowShouldClose(pWindow)) {
		_view->Update(glfwGetTimerValue() / 1000.0f);
		_view->GetRenderer()->UpdateRenderTree();
		_view->GetRenderer()->RenderOffscreen();
		
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
		_view->SetSize(SCR_WIDTH, SCR_HEIGHT);
		glDisable(GL_SCISSOR_TEST);

		//glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
		glClearColor(0.0f, 0.0f, 0.25f, 0.0f);
		glClearStencil(0);
		glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

		glUseProgram(shaderProgram);
		glBindVertexArray(triangleVAO);
		glDrawArrays(GL_TRIANGLES, 0, 3);

		_view->GetRenderer()->Render();

		glfwSwapBuffers(pWindow);
		glfwPollEvents();
	}

	_view->GetRenderer()->Shutdown();
	_view->Release();

	glfwTerminate();
	return 0;
}

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 2 guests